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

 
A100:
Для справки: если оба ваши примера четко перевести на С++, то С++ выдаст ошибку в обоих случаях. MQL в 1-ом случае не выдает ошибку лишь потому что процесс компиляции (а не сам язык) отличается

Спасибо.

 
Andrey Barinov:

Спасибо.

Чтобы не быть голословным привожу аналог к последнему (немного подправил на свой манер):

#ifdef __cplusplus
class B;
class A {
        int f( B* b ) { return b->i; } //Error: E2315
        int i;
};
class B : public A {};
#endif

и к первоначальному сообщению

#ifdef __cplusplus
class B;
class A {
        void f() {}
        void g() { b->f(); } //Error: E2315
        B *b;
};
class B : public A {};
#endif
 

Я проверил, вариант Станислава успешно компилируется в VS 2010.  Кроме того, работает также и обращение к приватному полю, а не только к методу.   Так что, пожалуй, А100 погорячился в своих выводах на этот раз )

 
Alexey Navoykov:

Я проверил, вариант Станислава успешно компилируется в VS 2010.  Кроме того, работает также и обращение к приватному полю, а не только к методу.   Так что, пожалуй, А100 погорячился в своих выводах на этот раз )

А он точно соответствует https://www.mql5.com/ru/forum/1111/page1999#comment_5677254 ?

Выше мои варианты... выкладывайте код сюда - раз он сам не может выложить

Ошибки, баги, вопросы
Ошибки, баги, вопросы
  • 2017.08.29
  • www.mql5.com
Форум алго-трейдеров MQL5
 
A100:

А он точно соответствует https://www.mql5.com/ru/forum/1111/page1999#comment_5677254 ?

Выше мои варианты... выкладывайте код сюда - раз он сам не может выложить

А каким компилятором вы это компилировали?  У меня в VS 2010 ваш код не компилируется совсем по другой причине:  не определён класс B там, где вызывается метод этого класса.  Для этого нужно вынести определение g() за пределы класса.  И у Станислава именно так и было сделано.   Т.е. ваш код должен быть таким:

class B;
class A {
  void f() {}
  void g();
  B *b;
};
class B : public A {};


void A::g(void)
{
  b->f();
}

и это компилируется.

 
Alexey Navoykov:

А каким компилятором вы это компилировали?

По сути это ничего не меняет - ошибка при компиляции (у меня планшет - компилятор Borland)

#ifdef __cplusplus
class B;
class A {
        void f() {}
        void g();
        B *b;
};
class B : public A {};
void A::g() { b->f(); } //Error: E2247
#endif
 
A100:

По сути это ничего не меняет - ошибка при компиляции (у меня планшет - компилятор Borland)

Хм, значит надо лезть в стандарты языка и смотреть, чей компилятор косячит.
 
Alexey Navoykov:
Хм, значит надо лезть в стандарты языка и смотреть, чей компилятор косячит.
Второй вариант аналогичен

#ifdef __BORLANDC__
class B;
class A {
        int g( B * );
        int i;
};
class B : public A {};
int A::g( B *b ) { return b->i; } //Error: E224
#endif

Косячит VS 2010 потому что преодолевает private путем неявного преобразования от B* к A*


#ifdef __BORLANDC__

class B;
class A {
        int g( B * );
        int i;
};
class B : public A {};
int A::g( B *b ) { return ((A *)b)->i; } //нормально

#endif

 
Alexey Navoykov:
Хм, значит надо лезть в стандарты языка и смотреть, чей компилятор косячит.
gcc 7.2 компилит последний вариант, проверял тут
Compiler Explorer - C++
  • About the author
  • godbolt.org
These settings control how Compiler Explorer acts for you. They are not preserved as part of shared URLs, and are persisted locally using browser local storage.
 
Комбинатор:
gcc 7.2 компилит последний вариант, проверял тут

В итоге получается следующая таблица

class B;
class A {                                       //MQL //BCC //VS2010 //gcc
        int f1( B *b ) { return       b .i;   } // -     -     +        +
        int f2( B *b ) { return       b .g(); } // +     -     +        +
        int f3( B *b ) { return ((A *)b).i;   } // +     +     +        +
        int f4( B *b ) { return ((A *)b).g(); } // +     +     +        +
        int f5()       { return       b .i;   } // -     -     +        +
        int f6()       { return       b .g(); } // +     -     +        +
        int f7()       { return ((A *)b).i;   } // +     +     +        +
        int f8()       { return ((A *)b).g(); } // +     +     +        +
//---
        int g() { return 0; }
        int i;
        B *b;
};
class B : public A {};

И при этом msdn пишет: Управление доступом помогает предотвратить использование объектов в неправомерных целях. Такая защита теряется при выполнении явных преобразований типов (приведении типов).