错误、漏洞、问题 - 页 1206

 
stringo:

这就对了。优先考虑准确的并发性。而这确实是正确的。

你为什么需要这样的统一?统一处理不正确的设计方案

需要进行统一,以便同样的代码能在C++和MQL中同样工作。在C++中,这样的顺序是有原因的(!)(否则在某些时候会出现歧义)。最初我认为C++编译器有逻辑错误和/或甚至是错误,但现在我倾向于相信这样的做法是有客观原因的。 下面是MQL中的一个例子,它表明X::g是完全匹配的,但Y::g还是被调用了--和C++中一样,这与前面的例子相矛盾https://www.mql5.com/ru/forum/1111/page1223#comment_1074757

class A {};
class B : public A {};
class C : public B {};
class X {
public:
        virtual int g( C* c1, C* c2 ) { return ( 1 ); } //полное совпадение здесь
        virtual int g( C* c,  B* b )  { return ( 2 ); }
};
class Y : public C { //здесь ошибся, должно быть public : X
public:
        virtual int g( A* a, B* b ) { return ( 3 ); }
};
void OnStart()
{
        C* c = new C;
        Y* y = new Y;
        Print( y.g( c, c ));
}

结果:3

事实证明,C++有 "不合逻辑 "但不明确的顺序,而MQL有随机的顺序--如果有完全匹配的类型,在一种情况下调用基类,在另一种情况下调用派生类。

 
A100:

需要进行统一,以便同样的代码能在C++和MQL中同样工作。在C++中,这样做的顺序是有原因的(!)。最初我认为C++编译器有逻辑错误和/或甚至是错误,但现在我倾向于相信这种做法有客观原因。 这里有一个MQL中的例子,表明X::g是完全匹配的,但Y::g还是被调用了--就像C++中一样,这与前面的例子相矛盾

结果:3

事实证明,C++有 "不合逻辑 "但毫不含糊的顺序,而MQL有随机的顺序--在类型完全并发的情况下,基类被调用,派生类被调用。

你说的到底是哪个C++实现?这个实现与C++标准的对应程度如何。关于选择重载函数,C++标准是怎么说的?

实际上,你所描述的函数重载 是不正确设计的结果。

源代码移植是一个神话。只有测试程序在不同的C++环境下工作方式相同。真正的程序(我们说的是具有实际应用价值的数千行代码)在不同的环境中至少在某些方面会有不同的工作。而且,根本谈不上将MQL与C++统一起来--这是对基因库的浪费......

 
A100:

需要进行统一,以便同样的代码能在C++和MQL中同样工作。在C++中,这样的顺序是有原因的(!)(否则在某些时候会出现歧义)。最初我认为C++编译器有逻辑错误和/或甚至是错误,但现在我倾向于相信这样的做法是有客观原因的。 下面是MQL中的一个例子,它表明X::g是完全匹配的,但Y::g还是被调用了--和C++中一样,这与前面的例子相矛盾https://www.mql5.com/ru/forum/1111/page1223#comment_1074757

结果:3

事实证明,C++有 "不合逻辑 "但不明确的顺序,而MQL有一个随机的顺序--在精确类型匹配的情况下,在一种情况下调用基类,在另一种情况下调用派生类

在这个例子中你似乎搞错了,如果Y类是从X继承而不是从C继承,那么行为就会和前面的例子一样。
 
stringo:

关于选择重载函数的顺序,C++标准是怎么说的?

引用Strawstrup的话:"C++要求基类中的虚拟函数 和派生类中的替换函数之间有精确的类型匹配"。

我现在已经研究了这个问题,得出的结论是C++是正确的。在上面的两个例子中,派生类的g()隐藏了(而不是替代了)基类的g()。而虚拟性机制只有在替换发生时才会被激活,而替换需要精确的类型匹配(除了返回类型)。只有返回类型的准确性可以取决于特定的实现。

 
mql5:
在这个例子中你似乎搞错了,如果Y类是继承自X而不是C,那么行为就会和前面的例子一样。

是的,我在这里搞错了,原来C++和MQL都有毫不含糊的,但不同的替换和隐蔽的顺序。请看我在上一篇文章中关于替代和隐瞒的区别的论述

事实上,C++在隐藏时产生了一个警告,这告诉你这个顺序是故意选择的

class A {};
class B : public A {};

class X {
public:
        virtual int g( A* a )
        virtual int f( B* a )
};
class Y : public X {
public:
        virtual int g( A* a ) //подмена  X::g
        virtual int f( A* a ) //сокрытие X::f
};
 
A100:

是的,我在这里搞错了,原来C++和MQL都有毫不含糊的,但不同的替换和隐蔽的顺序。请看我在上一篇文章中关于替代和隐瞒的区别的论述

事实上,C++在隐藏时产生了一个警告,这表明这个顺序是有意选择的

MQL编译器在搜索一个方法(函数)时,并不考虑传递给父级的方法(函数),因为它似乎与MS的C++一样,比如说。

谢谢你的帖子,我们会讨论(考虑)的。

 
mql5:
MQL编译器在搜索一个方法(函数)时,不考虑传递给一个父级的方法(函数),因为它似乎与MS C++一样,是一种铸造。

谢谢你的留言,我们会讨论(考虑)的。

请注意,不仅是来自MS - 我使用Borland C++ 5.5.1

Stroustrup写道,否则可能会出现与 "超越类对象 的终点 "有关的不愉快的后果

 
A100:

引用Strawstrup的话:"C++要求基类中的虚拟函数 和派生类中的替换函数之间有精确的类型匹配"。

我现在已经研究了这个问题,得出的结论是C++是正确的。在上面的两个例子中,派生类的g()隐藏了(而不是替代了)基类的g()。而虚拟性机制只有在替换发生时才会被激活,而替换需要精确的类型匹配(除了返回类型)。只有返回类型的准确性可以取决于特定的实现。

等一下,等一下。我们正在讨论用不同的参数重载函数。

另一方面,虚拟函数总是有相同类型的参数。虚拟功能不在本讨论范围内

 
A100:

请注意,不仅是来自MS - 我使用Borland C++ 5.5.1

Stroustrup写道,否则可能会出现与 "超过类对象 的终点 "有关的不愉快的后果

我们已经讨论过这个问题;我们不会改变MQL编译器的行为--这是一个 "双刃棍"。让我解释一下。

这个问题只有在对现成的类进行修改时才有意义(在一个工作程序中)。
在父代有了更合适的函数后,程序将突然停止工作,因为调用的不是子代的方法,而是父代的方法。
那么,如果我们改变了MQL的行为,那么就会出现类似的情况--当给子代添加新的方法时,就会调用子代方法而不是父代函数(没有参数转换),而且是在参数转换的情况下,程序又会停止工作。

因此,除了与C++兼容之外,没有其他问题会得到解决,此外,编译器行为的改变会影响到现有的MQL程序。
 

Так как переменные типа структур и простых типов не имеют указателей, то применять к ним функцию GetPointer() запрещено.

也禁止将一个 指针作为参数传递给一个函数(哪一个?GetPointer或任何?)。在所有这些情况下,编译器将报告一个错误

引自文件。

class A{
public:
   void operator= (const A* from){
      if (GetPointer(this) == GetPointer(from))      // а тут я передаю и все ок
         Alert(1);                                  // резутат 1  из за того что передаю this
      else
         Alert(2);
   }
};

class B : public A{
public:
   void operator= (const B& from){  
      if (GetPointer(this) == GetPointer(from))
         return;
      operator=((A*)(GetPointer(this)));
   }
};
  B b;
   B bb;                        // забыл написать создание объектов и вызов функции.
   b = bb;

我已经明白了为什么它不骂人的警示--是我的错,因为我把一个错误的指针传入了一个函数。