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

 

Добрый день.

Мне одному кажется что вот такой код не должен компилироваться (должна быть private member access error)?

class cA;
class cB;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class cA
  {
   //====================
private:
   //====================
   //===============
   //===============
   cB               *B;
   //===============
   //===============
   void              testfunc(void){::Print(__FUNCSIG__);}
   //====================
public:
   //====================
   //===============
   //===============
   void              test(void)
     {
      ::Print(__FUNCSIG__);

      if(::CheckPointer(::GetPointer(this.B))==POINTER_INVALID)return;

      this.B.testfunc();   // Здесь идет вызов private метода объекта B, что вроде как не должно быть возможным
     }
   //===============
   //===============
   void              SetB(cB *const b){this.B=b;}
   //===============
   //===============
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class cB  : public cA
  {

  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   cA A;
   cB B;

   A.SetB(&B);
   A.test();

//---
   return(INIT_SUCCEEDED);
  }

В СД говорят что все ок, и так можно... 

 
Andrey Barinov:

Добрый день.

Мне одному кажется что вот такой код не должен компилироваться (должна быть private member access error)?

В СД говорят что все ок, и так можно... 

Согласно правилам MQL экземпляр класса может свободно обращаться к закрытым полям и методам другого экземпляра, если он принадлежит тому же классу, что и первый. Так-как сB наследуется от cA, то cB и есть cA, а следовательно cA может обращаться к любым закрытым методам и полям экземпляра cB, не зависимо от того, где он объявлен.

 
Vasiliy Sokolov:

Согласно правилам MQL экземпляр класса может свободно обращаться к закрытым полям и методам другого экземпляра, если он принадлежит тому же классу, что и первый. Так-как сB наследуется от cA, то cB и есть cA, а следовательно cA может обращаться к любым закрытым методам и полям экземпляра cB, не зависимо от того, где он объявлен.

Спасибо. В документации об этом не встречал. Можете ткнуть носом?
 
Andrey Barinov:
Спасибо. В документации об этом не встречал. Можете ткнуть носом?
В документации этого нет, т.к. является такой своеобразной недокументированной "фичей" языка. Фича очень странная и противоречивая, но тем не менее так сложилось.
 
Andrey Barinov:
Спасибо. В документации об этом не встречал. Можете ткнуть носом?

Это и в C++ так (а MQL строится по образу и подобию C++). Как говорят, приватность C++ - на уровне класса, а не объекта. Иначе было бы невозможно сделать, например, copy-конструктор, без специальных методов getter-ов для всех приватных полей.

 
Stanislav Korotky:

Это и в C++ так

А вы пробовали этот пример в С++ компилировать - или это общие теоретические рассуждения?
 
Andrey Barinov:
Спасибо. В документации об этом не встречал. Можете ткнуть носом?
Он сам это правило придумал. В документации сказано: 

Соответственно доступ к testfunc() возможен только (и только) из методов cA:: -> в данном случае из сA::test()

 
A100:
А вы пробовали этот пример в С++ компилировать - или это общие теоретические рассуждения?

А вы по ссылке пробовали переходить? Там можно не только откомпилировать, но и успешно выполнить пример.

 
Stanislav Korotky:

А вы по ссылке пробовали переходить? Там можно не только откомпилировать, но и успешно выполнить пример.

Почему тогда такой код не работает?

class cA;
class cB;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class cA
  {
private:
   int               m_var;
   int               m_func(void){return(this.m_var);}
public:
   void test(cB &b)
     {
      this.m_var=b.m_var;      // (1) 'm_var' - private member access error
       
      this.m_var=b.m_func();   // (2)  => norm
     }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class cB : public cA
  {
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   cA A;
   cB B;

   A.test(&B);
//---
   return(INIT_SUCCEEDED);
  }


Я не вижу разницы между (1) и (2).

 
Stanislav Korotky:

А вы по ссылке пробовали переходить? Там можно не только откомпилировать, но и успешно выполнить пример.

Обсуждается конкретный код приведенный выше. Если не пробовали - так и напишите