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

 
stringo:

Всё правильно. Приоритет отдаётся точному совпадению. И это действительно правильно

Зачем нужна такая унификация? Унифиикация обработки неправильно спроектированных программ

Унификация нужна, чтобы один и тот же код работал одинаково с С++ и MQL. В С++ такой порядок неспроста (!) сделан (в ином случае на каком то этапе возникают неоднозначности). Первоначально я подумал, что у С++ компилятора нелогичность и/или даже ошибка, но сейчас склоняюсь к тому, что есть объективные причины такого подхода.  Вот пример на MQL, который показывает, что полное совпадение у X:: g, а вызывается все равно Y::g - как в С++, что противоречит предыдущему примеру 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:

Унификация нужна, чтобы один и тот же код работал одинаково с С++ и MQL. В С++ такой порядок неспроста (!) сделан. Первоначально я подумал, что у С++ компилятора нелогичность и/или даже ошибка, но сейчас склоняюсь к тому, что есть объективные причины такого подхода.  Вот пример на MQL, который показывает, что полное совпадение у X:: g, а вызывается все равно Y::g - как в С++, что противоречит предыдущему примеру

Результат: 3

Получается, что у C++ "нелогичный", но однозначный порядок, а у MQL - случайный порядок - при точном совпадении типов в одном случае вызывается базовый класс - в другом производный

О какой конкретно реализации C++ Вы говорите? Насколько эта реализация соответствует стандарту С++. Что сказано в стандарте С++ про порядок выбора перегруженных функций?

На самом деле, описываемая Вами перегрузка функций является следствием неправильного проектирования.

Портирование исходников - это миф. В разных средах С++ одинаково работает только тестовая программа. Реальная программа (речь идёт о тысячах строк кода, имеющих реальное прикладное значение) в разных средах хоть в чём-то, но будет работать по-разному. А об унификации MQL с C++ вообще говорить нечего, растрата семенного фонда...

 
A100:

Унификация нужна, чтобы один и тот же код работал одинаково с С++ и MQL. В С++ такой порядок неспроста (!) сделан (в ином случае на каком то этапе возникают неоднозначности). Первоначально я подумал, что у С++ компилятора нелогичность и/или даже ошибка, но сейчас склоняюсь к тому, что есть объективные причины такого подхода.  Вот пример на MQL, который показывает, что полное совпадение у X:: g, а вызывается все равно Y::g - как в С++, что противоречит предыдущему примеру https://www.mql5.com/ru/forum/1111/page1223#comment_1074757

Результат: 3

Получается, что у C++ "нелогичный", но однозначный порядок, а у MQL - случайный порядок - при точном совпадении типов в одном случае вызывается базовый класс, а в другом - производный

Похоже, что Вы ошиблись в данном примере, если класс Y наследовать от X, а не от C, то поведение будет соответствовать предыдущему примеру.
 
stringo:

Что сказано в стандарте С++ про порядок выбора перегруженных функций?

Цитирую Строуструпа: "C++ требует точного соответствия типов виртуальной функции в базовом классе и подменяющей ее функции в производном классе"

Сейчас я разобрался в вопросе и пришел к выводу о правильности С++. В обоих приведенных выше примерах g() производного класса скрывает (а не подменяет) g() базового класса. А механизм виртуальности включается только когда идет подмена, а для подмены нужно точное соответствие типов (кроме возвращаемого). От конкретной реализации может зависеть только точность возвращаемого типа.

 
mql5:
Похоже, что Вы ошиблись в данном примере, если класс Y наследовать от X, а не от C, то поведение будет соответствовать предыдущему примеру.

Да здесь ошибся, таким образом получается и у С++ и у MQL однозначные, но разные порядки подмены и сокрытия. Посмотрите пожалуйста мои доводы в предыдущем посте о различии между подменой и сокрытием

Тот факт, что С++ при сокрытии выдает предупреждение, говорит о том, что такой порядок выбран умышленно

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:

Да здесь ошибся, таким образом получается и у С++ и у MQL однозначные, но разные порядки подмены и сокрытия. Посмотрите пожалуйста мои доводы в предыдущем посте о различии между подменой и сокрытием

Тот факт, что С++ при сокрытии выдает предупреждение, говорит о том, что такой порядок выбран умышленно

Компилятор MQL при поиске метода(функции) не считает переход к родителю за кастинг, как похоже это делает например C++ от MS.

Спасибо за сообщение, мы обсудим(подумаем) это.

 
mql5:
Компилятор MQL при поиске метода(функции) не считает переход к родителю за кастинг, как похоже это делает например C++ от MS.

Спасибо за сообщение, мы обсудим(подумаем) это.

Обратите внимание, что не только от MS - я использовал Borland C++ 5.5.1

Строуструп пишет, что в ином случае возможны неприятные последствия, связанные с "выходом за конец объекта класса

 
A100:

Цитирую Строуструпа: "C++ требует точного соответствия типов виртуальной функции в базовом классе и подменяющей ее функции в производном классе"

Сейчас я разобрался в вопросе и пришел к выводу о правильности С++. В обоих приведенных выше примерах g() производного класса скрывает (а не подменяет) g() базового класса. А механизм виртуальности включается только когда идет подмена, а для подмены нужно точное соответствие типов (кроме возвращаемого). От конкретной реализации может зависеть только точность возвращаемого типа.

Подождите, подождите. Речь идёт о перегрузке функций с разными параметрами.

Виртуальные же функции всегда имеют параметры того же самого типа. Виртуальные функции - вне этой нашей дискуссии

 
A100:

Обратите внимание, что не только от MS - я использовал Borland C++ 5.5.1

Строуструп пишет, что в ином случае возможны неприятные последствия, связанные с "выходом за конец объекта класса

Обсудили, менять поведение компилятора 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;

 По чему не ругается ??? за алерты уже понял - сам виноват не то в функцию передавал. 

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