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

 
Ilya Malev:

Спасибо за подробный ответ, однако, логику я немного не понял.

1) Почему компилятор воспринимает конструкцию B* b1=a как вызов оператора копирования А::А(const A&), (а не вызов B::B(const A&), ведь слева от оператора= находится именно класс B)

2) Почему компилятор не выдал предупреждения "конструктор копирования отсутствует"

3) Почему допускается "простой" вызов методов для несуществующих объектов (в то время как попытка непосредственно вызвать A::f() выдает ошибку компиляции "вызов не статического метода")

1) я написал что это явная ошибка, которую мы будем править в любом случае

2) конструктор копирования генерируется компилятором, если его не объявил пользователь

3) не совсем понятен вопрос.
    По контексту обсуждения:
    Можно долго спорить, как правильно, производить или нет "разыменование" указателя, если доступа по нему не будет?
    Операция разыменования (получение реального указателя из хендла) - это "внутренний" (не пользовательский) и дорогой (по сравнению с его отсутствием) код.
    Зачем производить разыменование, если доступа по указателю не будет ?
    Пока это останется так как есть, операция разыменования удаляется оптимизатором, если доступа по указателю не будет.

 
Ilya Malev:

4) Ну и почему компилятор допускает вообще "простой" вызов виртуального метода? По-моему, виртуальность никак не должна зависеть от наличия или отсутствия данных в объекте

Вы путаете тёплое с мягким.

Девиртуализация вызова - это отдельный метод оптимизации, никак не связанный с наличием или отсутствием полей в объекте.

 
Ilyas:

2) конструктор копирования генерируется компилятором, если его не объявил пользователь

Там слева стоит объект B, почему для него вызывается (или генерируется) конструктор A::A(A&) ?  Это противоречит принципам ООП
 
Alexey Navoykov:
Там слева стоит объект B, почему для него вызывается конструктор A::A() ?

Потому что в мкл так себя всегда ведут операторы =, ==, !=, !, && и || когда слева указатель, а справа типа "объект". И заодно эти операторы невозможно перегрузить на указателях.

Поэтому плиз разработчики, когда будете править этот баг - сделайте вышеуказанные операторы перегружаемыми для динамических объектов

 
Перестало работать приложение метатрейдер 4, при запуске работает где-то секунду, потом появляется окошко торговли в один клик в верхнем левом углу (Buy/Sell) и затем приложение закрывается.
Есть варианты как это можно исправить?
За помощь заранее благодарен.
 
Ilya Malev:

Потому что в мкл так себя всегда ведут операторы =, ==, !=, !, && и || когда слева указатель, а справа типа "объект".

Да при чём здесь указатель.  Я же вам вот здесь уже ответил. Оно и без указателя так работает здесь.
 
Alexey Navoykov:
Там слева стоит объект B, почему для него вызывается (или генерируется) конструктор A::A(A&) ?  Это противоречит принципам ООП

Полностью с Вами согласен и уже написал, что это ошибка, которая будет правиться.

В данном случае, компилятор подобрал подходящую перегрузку по наследованию, что нельзя было делать на конструировании объекта.

 
Ilyas:

    Можно долго спорить, как правильно, производить или нет "разыменование" указателя, если доступа по нему не будет?

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

Потому что список виртуальных методов - это часть информации объекта, не менее важная, чем собственно данные, и доступ к виртуальным методам - это и есть доступ по указателю. Например если я в своем примере напишу

  A* aa=a;
  B* b1=a;   
  b1=aa;
  b1.f();

То получу снова B::f(), хотя здесь уже явное идет присвоение указателю В* объекта А*, который и "скопирован" был из А, и находился по ссылке А* . Это уже глубже ситуация, чем вызов "не того" конструктора копирования. Хотя даже если бы у объекта не было виртуальных методов, проверить валидность указателя при доступе по нему следовало бы все равно. 

 
Alexey Navoykov:
Там слева стоит объект B, почему для него вызывается (или генерируется) конструктор A::A(A&) ?  Это противоречит принципам ООП

А Вы уверены что там вообще что-то вызывается? Я проверил в x32:

class A {
public:
        A()           { Print(__FUNCSIG__); }
        A( const A& ) { Print(__FUNCSIG__); }
} a;
class B : public A {
public:
        B()           { Print(__FUNCSIG__); }
        B( const B& ) { Print(__FUNCSIG__); }
} *b = a;
void OnStart() {}

Результат: A::A()
и больше - ничего!

 
A100:

А Вы уверены что там вообще что-то вызывается? Я проверил в x32:

Результат: A::A()
и больше - ничего!

Так, пошёл проверять дампы генератора/оптимизатора, чтобы расставить точки над и

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