Как инициализировать экземпляр класса и распечатать его публичную переменную?
У меня есть следующий код:
/* 1 */ class Market {
/* 2 */ public:
/* 3 */
/* 4 */ double foo;
/* 5 */
/* 6 */ /*
/* 7 */ * Constructor:
/* 8 */ */
/* 9 */ Market() {
/* 10 */ foo = 2;
/* 11 */ }
/* 12 */ };
/* 13 */
/* 14 */ Market market; // GLOBALLY VISIBLE VAR
/* 15 */
/* 16 */ void OnInit() { // OnInit event-process
/* 17 */ market = new Market(); // <------------------- 17,10
/* 18 */ Print(market.foo);
/* 19 */ }
/* 20 */
/* 21 */ void OtherFunc() {
/* 22 */ Print(market.foo);
/* 23 */ }
Однако, когда я пытаюсь скомпилировать, я получаю следующую ошибку:
test.mq4 (17,10):
error 280:
'=' - требуется объект
По сути, я планирую создать экземпляр объекта и получить указатель на него, чтобы я мог использовать его во всем коде.
Я проверил MQL4
страница документации о занятиях, но это мне не помогло.
Я также попытался назначить класс как:
Market *market = new Market();
а затем я объявил эту переменную в первой строке как:
Market market;
но тогда я получил это предупреждение:
test.mq4 (17,11):
warning 62:
декларация "рынок" скрывает глобальную декларацию в строке 14
и файл компилируется, но я не хочу скрывать глобальное объявление (так как оно не будет доступно в других функциях), я хочу назначить экземпляр объекта в глобальном объявлении, чтобы я мог распечатать переменную объекта через весь код
Как я могу это сделать?
3 ответа
Итак, давайте начнем "инвентаризацию не-с" в Advanced- MQL4
Первый совет, никогда не полагайтесь на веб-источники, всегда проверяйте автообновление IDE
- Help
, Даже это не содержит 100% правильных текстовых / кодовых примеров, но гораздо ближе к реальной грамматике компилятора, чем устаревшие веб-тексты.
Следующий совет, всегда помни MQL4
это не C
язык - странные различия могут убить умную идею.
Синтаксис FIRST:
Оператор создания объекта
new
new
Оператор автоматически создает объект соответствующего размера, вызывает конструктор объекта и возвращаетdescriptor
созданного объекта. В случае сбоя оператор возвращаетnull descriptor
это можно сравнить сNULL
постоянная.
new
оператор может применяться только кclass
объекты. Это не может быть применено к структурам.
Указатели объектов
ВMQL4
, есть возможность динамически создавать объекты сложного типа. Это сделаноnew
оператор, который возвращаетdescriptor
созданного объекта.Descriptor
имеет размер 8 байт. Синтаксически, дескрипторы объектов вMQL4
похожи на указатели вC++
,
Примеры:MyObject* hobject= new MyObject();
В отличие отC++
,hobject
переменная из примера выше - это не указатель на память, а объектdescriptor
, Кроме того, вMQL5
все объекты в параметрах функции должны передаваться по ссылке.
Сохранение значения, видимого в глобальной области видимости NEXT:
Используя вышеизложенное, hobject
должен быть видимым в глобальной области видимости, предполагая, что это объявление было в надлежащем месте, до того, как какой-либо системный обработчик событий / пользовательский код был запущен (и, конечно, при условии, что внутри какой-либо области действия более низкого уровня не происходит маскирование имен). диапазон кода).
Эпилог:
После воздействия немного больше, чем несколько hundreds man*years
из MQL4
Практический опыт, все передовые решения начали разрабатываться как распределенная структура, а не оставаться жертвами языковых нарушений и синтаксических крипов. Можно считать это несколько более безопасной альтернативой, чем инвестировать в экосистему какой-то замечательный объем разработки программного обеспечения, который меняется быстрее, чем экономия / производительность повторяющейся реинжиниринга кодовой базы, чтобы удержать темп движущихся песков.
В любом случае: Добро пожаловать в Дикие Миры
MQL4
Давайте разработаем кейс для каждого участника:
Более важная часть истории:
class
Синтаксис обеспечивает средства для очень важной концепции мышления. Граница объектов здесь служит кардинальным защитным барьером, а не просто очередной игрушкой-синтаксисом (в то время как некоторые языки применяют эту основную защиту барьера доступа, сохраняя внутренние миры объектов с абсолютной изоляцией от любых попыток внешне пытаются "напрямую" взаимодействовать с переменными экземпляра класса (такими как SmallTalk
делает это, на отличном уровне), некоторые другие языки, которые начали свои первые посещения ООП-территорий несколько замечательных десятилетий спустя, не проявляют такой ясности в ментальных концепциях и могут допускать "гибридный" доступ (который может и действительно сильно сбивать с толку) о конфликтующих методах программирования, что-то вроде обхода оригинальных основных преимуществ архитектуры OOD- все это на полном риске на стороне команд по программированию / тестированию).
// DEMO GetFoo:
public: double DEMO_GetFoo(){ return( aClassVARIABLE_foo );
}
или даже прямая печать <class-method>
// DEMO PrintActualFooVALUE:
public: void PrintActualFooVALUE(){ PrintFormat( "Value of foo == %23.10f",
aClassVARIABLE_foo
);
}
гораздо более устарели, защищая private: double aClassVARIABLE_foo;
из внешних миров, чем общепризнанное общественное разрешение испортить драгоценные игрушки-предметы голым (свободно обнаженным) public: double foo;
,
BEST PRACTICE: KEEP THE BENEFITS OF THE CORE MOTIVATION FOR OOD
Если можно так сделать,
предпочтительнее избегать таких опасностей и оттачивать свое мастерство в ООД.
Зачем? Ради академической чистоты?
Нет.
Во-первых, необходимо изменить неважные детали реализации внутриclass
научит одного, почему так важно должное разделение внутреннего мира объекта и внешнего мира реальности вне объекта.
Доступ через<class-methods>
полностью предотвращает и, в основном, избегает любых воздействий на базу кода вне модифицированногоclass
правильно, потому что доступ<class-methods>
отражать и опосредовать все внутренние изменения соответственно, без внешних миров когда-либо было необходимо знать детали о реальном внутреннем представлении класса (предположительно толькоdouble
)foo
или что-то более сложное, с чем нужно справиться.
С помощью
доступ по методам класса,
а не задания голому public: <class-variable>
,
код
может выглядеть так:
//+------------------------------------------------------------------+
//| ___Stackru_OOP_class_public_variable_DEMO.mq4 |
//| Copyright © 1987-2016 [MS] |
//| nowhere.no |
//+------------------------------------------------------------------+ >>> http://stackru.com/questions/37368437/how-to-initialize-a-class-instance-and-print-its-public-variable
#property copyright "Copyright © 1987-2016 [MS]"
#property link "nowhere.no"
#property version "1.00"
#property strict
class DEMO_Class_Market {
// public:
private:
double aClassVARIABLE_foo;
// DEMO GetFoo:
public: double DEMO_GetFoo(){
return( aClassVARIABLE_foo );
}
// DEMO ChgFoo:
public: double DEMO_ChgFoo( double aNewVALUE_to_SET = EMPTY_VALUE ){
double aTempRetVALUE = aClassVARIABLE_foo;
aClassVARIABLE_foo = aNewVALUE_to_SET;
return( aTempRetVALUE );
}
// DEMO_<Constructor>:
DEMO_Class_Market(){
PrintFormat( "DEMO_Class_Market::<Constructor> has initially seen a variable foo == %23.10f", aClassVARIABLE_foo );
aClassVARIABLE_foo = 2.;
PrintFormat( "DEMO_Class_Market::<Constructor> has set a new value into var. foo == %23.10f", aClassVARIABLE_foo );
}
// DEMO_<Destructor>:
~DEMO_Class_Market(){
PrintFormat( "DEMO_Class_Market::<Destructor> has seen a current value of a foo == %23.10f", aClassVARIABLE_foo );
}
};
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart(){
DEMO_Class_Market anInstanceOfMARKET;
double anExternalQueryForClassVariableVALUE = EMPTY;
int aReturnCODE = GetClassInstancePublicVariableVALUE( anInstanceOfMARKET, anExternalQueryForClassVariableVALUE );
PrintFormat( "1.st call to GetClassInstancePublicVariableVALUE( anInstanceOfMARKET, ... ) function. The actual call returned [aReturnCODE == %d ], the anExternalQueryForClassVariableVALUE is == %23.10f", aReturnCODE, anExternalQueryForClassVariableVALUE );
aReturnCODE = ChgClassInstancePublicVariableVALUE( anInstanceOfMARKET, 6666.6666, anExternalQueryForClassVariableVALUE );
PrintFormat( "1.st call to ChgClassInstancePublicVariableVALUE( anInstanceOfMARKET, 6666.6666 ) function. The actual call returned [aReturnCODE == %d ], the returned previous value of a class-[private] variable was == %23.10f", aReturnCODE, anExternalQueryForClassVariableVALUE );
aReturnCODE = GetClassInstancePublicVariableVALUE( anInstanceOfMARKET, anExternalQueryForClassVariableVALUE );
PrintFormat( "2.st call to GetClassInstancePublicVariableVALUE( anInstanceOfMARKET, ... ) function. The actual call returned [aReturnCODE == %d ], the anExternalQueryForClassVariableVALUE is == %23.10f", aReturnCODE, anExternalQueryForClassVariableVALUE );
}
//+------------------------------------------------------------------+
#define RET_OK 0
#define RET_ERROR EMPTY
#define VAL_ERROR EMPTY_VALUE
//+------------------------------------------------------------------+
int GetClassInstancePublicVariableVALUE( DEMO_Class_Market &aClassINSTANCE, // |-> DEMO_Class_Market INSTANCE = <aClassINSTANCE> of a type DEMO_Class_Market
double &aDoubleVALUE // <=| returns RESULT = ???.???
){
aDoubleVALUE = aClassINSTANCE.DEMO_GetFoo(); // STOR <class-method> RET VALUE IN RESULT
return( RET_OK ); // FLAG RET_OK in JIT/RET
}
//+------------------------------------------------------------------+
int ChgClassInstancePublicVariableVALUE( DEMO_Class_Market &aClassINSTANCE, // |-> DEMO_Class_Market INSTANCE = <aClassINSTANCE> of a type DEMO_Class_Market
double const aNewDoubleVALUEtoSET, // |-> a value to SET
double &aReplacedVALUE // <=| returns an OLD value
){
aReplacedVALUE = aClassINSTANCE.DEMO_ChgFoo( aNewDoubleVALUEtoSET ); // CHNG NEW VALUE IN VARIABLE via <class-method>, RET OLD VALUE
return( RET_OK ); // FLAG RET_OK in JIT/RET
}
//+------------------------------------------------------------------+
Результаты из [ MT4 Terminal ] переупорядочены в соответствии с течением времени
2016.11.03 14:35:37.655 Script ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: loaded successfully
2016.11.03 14:35:37.655 ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: initialized
2016.11.03 14:35:37.655 ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: DEMO_Class_Market::<Constructor> has initially seen a variable foo == 0.0000000000
2016.11.03 14:35:37.655 ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: DEMO_Class_Market::<Constructor> has set a new value into var. foo == 2.0000000000
2016.11.03 14:35:37.655 ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: 1.st call to GetClassInstancePublicVariableVALUE( anInstanceOfMARKET, ... ) function. The actual call returned [aReturnCODE == 0 ], the anExternalQueryForClassVariableVALUE is == 2.0000000000
2016.11.03 14:35:37.655 ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: 1.st call to ChgClassInstancePublicVariableVALUE( anInstanceOfMARKET, 6666.6666 ) function. The actual call returned [aReturnCODE == 0 ], the returned previous value of a class-[private] variable was == 2.0000000000
2016.11.03 14:35:37.655 ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: 2.st call to GetClassInstancePublicVariableVALUE( anInstanceOfMARKET, ... ) function. The actual call returned [aReturnCODE == 0 ], the anExternalQueryForClassVariableVALUE is == 6666.6666000000
2016.11.03 14:35:37.655 ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: DEMO_Class_Market::<Destructor> has seen a current value of a foo == 6666.6666000000
2016.11.03 14:35:37.655 ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: uninit reason 0
2016.11.03 14:35:37.655 Script ___Stackru_OOP_class_public_variable_DEMO XAUUSD,H1: removed
Объявление о том, что в глобальной / локальной области не требуется никаких других изменений в синтаксисе:
Можно просто протестировать обе альтернативы декларации через взаимоисключающие (не) прокомментированные первый и второй экземпляры декларации.
.
..
...
DEMO_Class_Market anInstanceOfMARKET; // DECLARE'd on a global scope
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart(){
// DEMO_Class_Market anInstanceOfMARKET; // DECLARE'd on a local scope
...
..
.
Менее важная часть истории:
(cit.) "практический пример кода, как назначить / присоединить экземпляр объекта к глобальной переменной."
Это было показано в приведенном выше
MQL4
код на практике,
как было запрошено в пункте о вознаграждении,
что экземпляр класса может быть свободно присоединен кMQL4
переменная, существующая в глобальной или локальной области.
В случае, если необходимо выполнить некоторые специфичные для контекста инициализации при посещении с целью выполнения кодаOnInit()
обработчик события,
можно скорее оформить дополнительный (почти питонический: о))<class-method>
public: void __init__( ... ){ ... }
получить дополнительные уровни контроля
для такого контекстно-зависимого / MT4-состояния<class-instance>
настройки инициализации во времяOnInit()
и запросить там звонокanInstanceOfMARKET.__init__( ... );
как только детали графика [ MetaTrader Terminal 4 ] станут известны, а его параметры и другой цифровой контент станут доступными в режиме реального времени исполненияMQL4
-код (который не гарантируется в тот момент, когда процесс создания класса происходит прямо в коде объявления в месте, допустимом для определения в глобальной области).
Объявление глобальной переменной должно выглядеть так:
Market *market;
затем инициализировать класс (например, в OnInit()
) вы должны сделать как:
market = new Market();
Затем выведите переменные класса (например, market.foo
) или вызовите методы как обычно (например, market.Foo()
).