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

 

Все верно, нельзя приводиться снизу вверх, только сверху вниз. Это ради безопасности.

С С++ сравнивать нельзя - там все что угодно к чему угодно привести можно.

 
Комбинатор:
в С++ это тоже возможно только если указатель на базовый класс указывает на потомка.

Не понял что вы хотели этим сказать, но этот код:

class CLASS1
{
public:
  int i;  
};

class CLASS2 : public CLASS1 {};

int main() {
  CLASS1 _object;
  CLASS2 *_ptr = (CLASS2*)&_object;  
  _ptr->i = 1;

   return 0;
}

в С++ работает, о чем я и написал выше. А вот этот же код (учитывая синтаксис MQL):

class CLASS1
{
public:
  int i;  
};

class CLASS2 : public CLASS1 {};

int OnInit() {
  CLASS1 _object;
  CLASS2 *_ptr = dynamic_cast<CLASS2 *>(&_object);
  
  _ptr.i = 1;

   return 0;
}
уже не работает, т.к. _ptr получает NULL
Поэтому и возникает вопрос, это баг MQL и будет исправлен или так все и останется дальше?
 
Renat Fatkhullin:

Все верно, нельзя приводиться снизу вверх, только сверху вниз. Это ради безопасности.

С С++ сравнивать нельзя - там все что угодно к чему угодно привести можно.


теперь понятно, спс за разъяснения ))
 
Konstantin:

Не понял что вы хотели этим сказать, но этот код:

Ну так попытайтесь понять. Для начала заставьте dynamic_cast работать в плюсах. Разберетесь самостоятельно -- отложится гораздо лучше.
 
Renat Fatkhullin:

Все верно, нельзя приводиться снизу вверх, только сверху вниз.

В смысле нельзя приводить от базового класса к потомку?
 
Комбинатор:
В смысле нельзя приводить от базового класса к потомку?

Да, в случае когда на базовом не лежит реально сконструированный потомок.

 
Renat Fatkhullin:

Все верно, нельзя приводиться снизу вверх, только сверху вниз. Это ради безопасности.

если мы приведем указатель сверху вниз, т.е. к родителю, после чего передадим указатель куда нить в другую область видимости, то там будут доступны поля потомка?
 
Renat Fatkhullin:

Да.

Ренат, вы в курсе что такое dynamic_cast?
 
Комбинатор:
Ренат, вы в курсе что такое dynamic_cast?

Конечно.

Вы посмотрите на обсуждаемый кусок кода MQL5. Создается экземпляр базовый, а потом героически пытается преобразоваться через динамик каст в потомка в нарушение системы безопасности. Ну и облом конечно.

 

В документации прямо этот же пример рассмотрен и объяснен. Динамический кастинг при исполнении срабатывает только после прохождения проверки системы безопасности и допустимости преобразований. У каждого объекта MQL5 есть вся мета-информация для проверки прав во время исполнения. Это не пустой С++.


Динамическое приведение типов  с помощью оператора dynamic_cast

Существует возможность динамического приведения типов с помощью оператора dynamic_cast, который может быть применён только к указателям классов. При этом проверка корректности типов производится в момент выполнения программы. Это означает, что при использовании оператора dynamic_cast компилятор не производит проверку типа данных, используемого для приведения. В случае, если осуществляется преобразование указателя к типу данных, который не является фактическим типом объекта, результатом  будет  значение NULL.

dynamic_cast <type-id> ( expression )

Параметр type-id в угловых скобках должен быть указателем на ранее определённый тип класса. Тип операнда expression (в отличии от C++) может быть любым, кроме void.

Пример:

class CBar { };
class CFoo : public CBar { };
 
void OnStart()
  {
   CBar bar;    
//--- динамическое приведение типа указателя *bar к указателю *foo разрешено 
   CFoo *foo = dynamic_cast<CFoo *>(&bar); // критической ошибки выполнения не возникнет   
   Print(foo);                             // foo=NULL      
//--- попытка явного приведения ссылки объекта типа Bar к объекту типа Foo запрещено
   foo=(CFoo *)&bar;                       // возникнет критическая ошибка выполнения
   Print(foo);                             // эта строка не будет выполнена
  }

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