错误、漏洞、问题 - 页 2657

 
Stanislav Korotky:

这就是问题所在,类树有一个共同的节点CWnd(CObject离得更远,在根部)。

CButton -> CWndObj -> CWnd -> CObject。

如果你把方法中的参数改为CObject,你会得到2倍的错误。

类似的类层次结构适用于非数组的情况。以下是编译后的代码。

问题是如何让它对阵列也起作用?

我知道模板有帮助,但我只想避免它。

IMHO,它应该通过继承权在没有模板的情况下工作。

我像在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对继承者起作用(更长的链),也就是说,如果指向基的指针包含派生,那么你可以投向派生,如果它不是NULL(即投得正常),就调用它的方法。但是,当情况相反时,就像我的情况一样,存在着派生的指针,那么根据定义,它也是基础。而任何对其虚拟方法的调用都会发现派生是 "坐在 "指针中的,并调用重写的实现。需要的是基础的那个。

在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函数将伪随机数发生器设置为初始状态。

我不想翻阅源代码,但对于神经网络包来说,通过NS权重的随机值进行初始化是强制性的,我怀疑这是按MQL帮助材料进行的--即使用了srand()。

也就是说,在测试器内使用这样的NS包的MQL-程序很可能发生在一个处理器核心上--初始NS权重会有相同的值,对吗?

没有srand()就更酷了。

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

这与文件相抵触https://www.mql5.com/ru/docs/math/mathrand

我不想翻看源代码,但对于神经网络包来说,通过NS权重的随机值进行初始化是强制性的,我怀疑这是按MQL帮助材料做的--即使用了srand()。

也就是说,在测试器内使用这样的NS包的MQL-程序很可能发生在一个处理器核心上--初始NS权重将有相同的值,对吗?

如果没有srand(),就更有趣了

Igor,那就试试MathSrand(int(GetMicrosecondCount()%16384))。

我想知道形象会有什么变化。