Как инициализировать экземпляр класса и распечатать его публичную переменную?

У меня есть следующий код:

/*  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()).

Другие вопросы по тегам