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

 
Renat Fatkhullin:

Конечно.

Точно? Потому что dynamic_cast чаще всего как раз нужен для приведения снизу вверх, от родителя к потомку.

Мало того, в MQL он отлично приводит снизу вверх даже в том случае когда не должен:

class A
{
public:
   virtual void f()
   {
      Print("1");
   }
};

class B: public A
{
public:
   virtual void f()
   {
      Print("2");
   }
};

void OnStart()
{
   A* ptr1 = new B();
   ptr1.f();
   A* ptr2 = new A();
   ptr2.f();
   
   B* casted = dynamic_cast<B*>(ptr1);
   casted.f();
   
   B* casted1 = dynamic_cast<B*>(ptr2);
   casted1.f(); // здесь должна быть ошибка потому что casted1 должен быть null
   delete ptr1;
   delete ptr2;
}

вывод:
2017.05.13 18:30:14.864    t ETHUSD,M5: 2
2017.05.13 18:30:14.865    t ETHUSD,M5: 1
2017.05.13 18:30:14.866    t ETHUSD,M5: 2
2017.05.13 18:30:14.867    t ETHUSD,M5: 2


Renat Fatkhullin:

Вы посмотрите на обсуждаемый кусок кода MQL5.

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

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

Да, вот пример, демонстрирующий ваш вопрос:

class CLASS1
  {
public:
   int               i;
  };
class CLASS2 : public CLASS1
  {
  };
void OnStart()
  {
   CLASS1 _object;
   CLASS2 *_ptr=dynamic_cast<CLASS2 *>(&_object);

   if(!_ptr)
      Print("CLASS1 -> CLASS2 failed, null");

   CLASS2 *my=new CLASS2;
   CLASS1 *my_ptr=my;
   CLASS2 *my_ptr2=dynamic_cast<CLASS2 *>(my_ptr);

   if(my_ptr2)
     {
      Print("CLASS2 -> CLASS1 -> CLASS2 ok");
      my_ptr2.i=1;
     }
   Print("Value: ",my.i);
  }
и вывод:
2017.05.13 18:34:50.341 cast (EURUSD,H1)        CLASS1 -> CLASS2 failed, null
2017.05.13 18:35:18.933 cast (EURUSD,H1)        CLASS2 -> CLASS1 -> CLASS2 ok
2017.05.13 18:35:20.110 cast (EURUSD,H1)        Value: 1

Сначала проверяем неразрешенный кастинг снизу вверх и получаем NULL. Все верно.

Потом создаем объект CLASS2, присваиваем ссылку на него родительскому классу (тут важно понять, что в динамике среда знает, что исконный тип объекта CLASS2 - это хранится в его метаинформации). Далее (как раз ваш вопрос) динамически кастим (с проверкой права преобразования на основе метаинформации исходного объекта) из ссылки CLASS1 в CLASS2.

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

Все работает верно и по спецификации (включая dynamic_cast спеку самого C++).

 
Комбинатор:

Точно? Потому что dynamic_cast чаще всего как раз нужен для приведения снизу вверх, от родителя к потомку.

Мало того, в MQL он отлично приводит снизу вверх даже в том случае когда не должен:

Точно:

Не забывайте обновляться на последние билды. Я сейчас тестируюсь на 1598, который выкладывался недавно в виде зипов в этой ветке вроде.

 
Renat Fatkhullin:

Не забывайте обновляться на последние билды.

Да, старый билд.

Renat Fatkhullin:

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

Вы вот это потрите, вводит в заблуждение и напрямую противоречит функционированию dynamic_cast
 
Комбинатор:

Да, старый билд.

Вы вот это потрите, вводит в заблуждение и напрямую противоречит функционированию dynamic_cast

В рамках поднятого примера кастинга в лоб CLASS1 -> CLASS2 все верно сказал. Именно такой кастинг в большинстве случаев люди и имеют в голове.

Кроме того, именно "нельзя приводиться снизу вверх, только сверху вниз" лежит в основе проверки безопасности dynamic_cast.

Те, кто знает что делает, тот понимает суть динамического кастинга.

 
Renat Fatkhullin:

Не забывайте обновляться на последние билды. Я сейчас тестируюсь на 1598, который выкладывался недавно в виде зипов в этой ветке вроде.

Компилятор и исполнитель в каком exe-файле сидит?

Сейчас в MT4b1080 идет MEb1599. Прошу пояснить, что делает metaeditor.exe и terminal.exe.

 
fxsaber:

Компилятор и исполнитель в каком exe-файле сидит?

Сейчас в MT4b1080 идет MEb1599. Прошу пояснить, что делает metaeditor.exe и terminal.exe.

Компилятор для обоих платформ единый. Он в metaeditor.exe
 
Renat Fatkhullin:
Компилятор для обоих платформ единый. Он в metaeditor.exe
А исполнитель, который проверяет тот же dynamic_cast, в terminal.exe ?
 
fxsaber:
А исполнитель, который проверяет тот же dynamic_cast, в terminal.exe ?
Конечно
 
Renat Fatkhullin:
Еще такой вопрос
Причина обращения: