Errors, bugs, questions - page 1206

 
stringo:

That's right. Priority is given to exact match. And it's really right.

Why do you need such unification? Unification of processing incorrectly designed programs

Unification is needed so that the same code works equally with C++ and MQL. In C++, this order is done (!) for a reason (otherwise there are ambiguities at some point). Originally I thought that C++ compiler has illogic and/or even a bug, but now I'm inclined to believe that there are objective reasons for such an approach. Here is an example in MQL, which shows that X:: g is a full match, but Y::g is called anyway - as in C++, which contradicts the previous example 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 ));
}

Result: 3

It turns out that C++ has "illogical" but unambiguous order, while MQL has a random order - if there is an exact match of types, a base class is called in one case and a derived class in the other

 
A100:

Unification is needed so that the same code works equally with C++ and MQL. In C++, this order is done (!) for a reason. Originally I thought that C++ compiler has illogic and/or even a bug, but now I'm inclined to believe that there is an objective reason for such an approach. Here is an example in MQL that shows that X:: g is a full match, but Y::g is called anyway - as in C++, which contradicts the previous example

Result: 3

It turns out that C++ has "illogical" but unambiguous order, while MQL has a random order - with exact concurrency of types the base class is called in one case and the derived class in the other

Which C++ implementation exactly are you talking about? How well does this implementation correspond to the C++ standard. What does the C++ standard say about choosing overloaded functions?

Actually, the function overloading you describe is a consequence of incorrect design.

Source code porting is a myth. Only the test program works the same way in different C++ environments. The real program (we are speaking of thousands of lines of code with a real application value) will work differently at least in some aspects in different environments. And there's nothing to speak of unifying MQL with C++ at all - it's a waste of the gene pool...

 
A100:

Unification is needed so that the same code works equally with C++ and MQL. In C++, this order is done (!) for a reason (otherwise there are ambiguities at some point). Originally I thought that C++ compiler has illogic and/or even a bug, but now I'm inclined to believe that there are objective reasons for such an approach. Here is an example in MQL, which shows that X:: g is a full match, but Y::g is called anyway - as in C++, which contradicts the previous example https://www.mql5.com/ru/forum/1111/page1223#comment_1074757

Result: 3

It turns out that C++ has "illogical" but unambiguous order and MQL has a random order - in case of exact type matching, a base class is called in one case and a derived class in another case

You seem to be mistaken in this example, if class Y is inherited from X and not from C, then the behaviour would be the same as in the previous example.
 
stringo:

What does the C++ standard say about the order of selecting overloaded functions?

To quote Strawstrup: "C++ requires an exact type match between the virtual function in the base class and the substituted function in the derived class".

I have now looked into the issue and come to the conclusion that C++ is correct. In both examples above, g() of the derived class hides (rather than substitutes) g() of the base class. And the virtuality mechanism is only activated when substitution takes place, and substitution requires exact type matching (except for the return type). Only the accuracy of the return type can depend on the particular implementation.

 
mql5:
You seem to be mistaken in this example, if class Y is inherited from X and not from C, the behaviour would be the same as the previous example.

Yes, I was mistaken here, so it turns out that both C++ and MQL have unambiguous, but different orders of substitution and concealment. Please see my arguments in the previous post about the difference between substitution and concealment

The fact that C++ generates a warning when hiding tells you that this order is chosen intentionally

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:

Yes, I was mistaken here, so it turns out that both C++ and MQL have unambiguous, but different orders of substitution and concealment. Please see my arguments in the previous post about the difference between substitution and concealment

The fact that C++ generates a warning when hiding indicates that this order is chosen intentionally

The MQL compiler when searching for a method (function) doesn't consider passing to a parent as a casting, as it seems to do with C++ from MS, for example.

Thanks for the post, we'll discuss(think about it).

 
mql5:
The MQL compiler when searching for a method (function) does not consider passing to a parent as a casting, as it seems to do with MS C++ for example.

Thanks for the message, we will discuss(think about it).

Note that not only from MS - I used Borland C++ 5.5.1

Stroustrup writes that otherwise there may be unpleasant consequences related to "going beyond the end of the class object"

 
A100:

To quote Strawstrup: "C++ requires an exact type match between the virtual function in the base class and the substituted function in the derived class".

I have now looked into the issue and come to the conclusion that C++ is correct. In both examples above, g() of the derived class hides (rather than substitutes) g() of the base class. And the virtuality mechanism is only activated when substitution takes place, and substitution requires exact type matching (except for the return type). Only the accuracy of the return type can depend on the particular implementation.

Wait a minute, wait a minute. We're talking about overloading functions with different parameters.

Virtual functions, on the other hand, always have parameters of the same type. Virtual functions are outside the scope of this discussion

 
A100:

Note that not only from MS - I used Borland C++ 5.5.1

Stroustrup writes that otherwise there may be unpleasant consequences related to "going over the end of the class object"

We've discussed this; we're not going to change the MQL compiler's behaviour - it's a "two-edged stick". Let me explain.

The problem is relevant only when modifications are made to the ready-made classes (in a work program).
After the parent has a more suitable function, the program will suddenly stop working, because instead of the method of the descendant the method of the parent has been called.
Well, if we change MQL behavior, then a similar situation can occur - when adding a new method to the descendant, instead of the parent function (without parameter casting) the descendant method is called, and with parameter casting, and the program stops working again.

Thus, no problems other than compatibility with C++ will be solved, besides, the change of compiler's behavior will affect existing MQL programs.
 

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

It is also prohibitedto pass a pointeras an argument to a function (which one ???GetPointer or any ?).In all these cases, the compiler will report an error.

Quote from the documentation.

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;

I've already understood why it's not scolding for alerts - it's my fault I passed a wrong pointer into a function.

Reason: