Ошибки, баги, вопросы - страница 2657

 
Stanislav Korotky:

В том то и дело что дерево классов имеет общий узел CWnd (CObject дальше, вообще в корне).

CButton -> CWndObj -> CWnd -> CObject.

Если изменить параметр в методе на CObject, получаем в 2 раза больше ошибок:

Аналогичная иерархия классов работает для случая не массива. Вот компилируемый код:

Вопрос, как сделать, чтобы и для массива работало?

Я знаю шаблон помогает, но его как раз хочется избежать.

ИМХО, должно без шаблонов работать по праву наследования.

Проверил как в C++.

Работает. Но MQL такое не переваривает, что с индексом, что без.

Для C++ вот так наглядней Ваш пример будет. Запустите и посмотрите, что получится)))

class CWnd
{
public:
    int x;
    CWnd(int _x = 10) : x(_x) {}
};
class CButton : public CWnd
{
    int a;
public:
    CButton(int _a=6) : CWnd(),a(_a) {}
};

class Collection
{
public:
    Collection(CWnd* ptr,size_t size) {
        for (int i = 0; i < size; cout << ptr[i++].x<<endl);
    }
};

int main()
{
    CButton buttons[10];
    CWnd wnd[10];
    Collection data1(&wnd[0],_countof(wnd));
    cout << "------------------------------" << endl;
    Collection data2(&buttons[0],_countof(buttons));
    return 0;
}
 

Мда, мой косяк. Но тогда возникает следующий вопрос. Вот этот код C++ работает (уже точно как надо ;-)).

class Base
{
  public:
    virtual void method1(void) { cout << "2\n"; }
};

class Derived: public Base
{
  public:
    virtual void method1(void) override { cout << "3\n"; }
};

template<typename T>
class Wrapper
{
  public:
    Wrapper(T *ptr)
    {
      ptr->T::method1();
    }
};

int main()
{
  Derived d;
  d.Base::method1();   // ok
  Wrapper<Base> w(&d); // ok

  return 0;
}

Аналогичный MQL дает ошибку:

class Base
{
  public:
    virtual void method1(void) { Print(__FUNCSIG__); }
};

class Derived: public Base
{
  public:
    virtual void method1(void) override { Print(__FUNCSIG__); }
};

template<typename T>
class Wrapper
{
  public:
    Wrapper(T *ptr)
    {
      ptr.T::method1(); // <<< 'Base' is not a class, struct or union
    }
};


void OnStart()
{
  Derived d;
  d.Base::method1();   // ok
  Wrapper<Base> w(&d); // causes the error above
 
Stanislav Korotky:

Мда, мой косяк. Но тогда возникает следующий вопрос. Вот этот код C++ работает (уже точно как надо ;-)).

Аналогичный MQL дает ошибку:

не знаю задачу, но по моему Вы ищете что то такое:

typedef void(*PTR)(void);

в MQL это указатель на функцию  void func(void)

 в классе можно объявить поле с типом PTR и затем присвоить ему функцию и затем "разыменовывать указатель" и вызвать функцию 

с передачей функций написанных в процедурном стиле в класс работает без проблем, методы класса, скорее всего, так просто не получится передавать, можно через dynamic_cast  попробовать, но код очень запутанный получится

 
Igor Makanu:

не знаю задачу, но по моему Вы ищете что то такое:

в MQL это указатель на функцию  void func(void)

 в классе можно объявить поле с типом PTR и затем присвоить ему функцию и затем "разыменовывать указатель" и вызвать функцию 

с передачей функций написанных в процедурном стиле в класс работает без проблем, методы класса, скорее всего, так просто не получится передавать, можно через dynamic_cast  попробовать, но код очень запутанный получится

typedef не прокатит с методом.

dynamic_cast работает в сторону наследника (более длинной цепочки), то есть если в указателе на base содержится derived, то можно привести к derived и, если он не NULL (т.е. каст нормальный),  вызвать его метод. Но когда ситуация наоборот, как в моем случае, есть указатель на derived то он по определению является и base. И любой вызов его виртуального метода просекает, что в указателе "сидит" derived и вызывает переопределенную реализацию. А нужно базовую.

Для этого есть вышеуказанная синтаксическая конструкция в C++, но MQL - не C++. По-видимому, пока никак.

Я сделал у себя обходной трюк, но он не во всех задачах может прокатить.

Смысл всех этих плясок с бубном, как всегда, чтобы запутанный код остался внутри "библиотеки", а использующий её код стал кристально чистым и простым.

 

чем инициализировать в тестере rand() ?

код:

input ulong param = 18446744073709551615;
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      srand(GetTickCount()); 
      return(rand());
   }
//+------------------------------------------------------------------+

мне не совсем нравится такая псевдослучайная генерация:


 
Igor Makanu:

чем инициализировать в тестере rand() ?

код:

мне не совсем нравится такая псевдослучайная генерация:


Справка: MathRand

Примечание

Перед первым вызовом функции необходимо использовать функцию MathSrand, чтобы перевести генератор псевдослучайных чисел в начальное состояние.


Попробуйте теперь с MathSrand.

Документация по MQL5: Математические функции / MathRand
Документация по MQL5: Математические функции / MathRand
  • www.mql5.com
Математические функции / MathRand - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Vladimir Karputov:

Справка: MathRand

Примечание

Перед первым вызовом функции необходимо использовать функцию MathSrand, чтобы перевести генератор псевдослучайных чисел в начальное состояние.

Спасибо, Кэп !

речь идет о тестере

этот код тоже не работает в ТЕСТЕРЕ

input ulong param = 18446744073709551615;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
   {
   MathSrand(GetTickCount()); 
   return(INIT_SUCCEEDED);
   }
//+------------------------------------------------------------------+
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      return(rand());
   }
//+------------------------------------------------------------------+
 
Igor Makanu:

думаю, что, если тестер, то не нужно использовать MathSrand.

Но если это не поможет, тогда скорей всего принудительно на каком-то этапе тестер вызывает MathSrand(GetTickCount())

Тогда можно попробовать MathSrand(int(GetMicrosecondCount()%1000000)); 

ЗЫ ведь нужно помнить, что GetTickCount() меняет свои значения каждые 15.625 милисекунд. Это очень большой промежуток времени для тестера.

 
Nikolai Semko:

думаю, что, если тестер, то не нужно использовать MathSrand.

это противоречит документации https://www.mql5.com/ru/docs/math/mathrand

Перед первым вызовом функции необходимо использовать функцию MathSrand, чтобы перевести генератор псевдослучайных чисел в начальное состояние.

не хочу алглиб исходники листать, но для нейросетевых пакетов инициализация рендомным значением весов НС это обязательно, подозреваю, что и делалось по материалом справки MQL - т.е. использовался srand()

т.е. использование внутри тестера  MQL-программ с таким НС-пакетом будет проходить, скорее всего, по сути на одном ядре процессора - начальные веса НС будут же иметь одинаковые значения?

без srand() еще прикольнее

int OnInit()
   {
   return(INIT_SUCCEEDED);
   }
//+------------------------------------------------------------------+
void OnTick()
   {
   }
//+------------------------------------------------------------------+
double OnTester()
   {
      return(rand());
   }
//+------------------------------------------------------------------+
 
Igor Makanu:

это противоречит документации https://www.mql5.com/ru/docs/math/mathrand

не хочу алглиб исходники листать, но для нейросетевых пакетов инициализация рендомным значением весов НС это обязательно, подозреваю, что и делалось по материалом справки MQL - т.е. использовался srand()

т.е. использование внутри тестера  MQL-программ с таким НС-пакетом будет проходить, скорее всего, по сути на одном ядре процессора - начальные веса НС будут же иметь одинаковые значения?

без srand() еще прикольнее

Игорь, ну тогда попробуй MathSrand(int(GetMicrosecondCount()%16384)); 

Интересно как картина измениться

Причина обращения: