Ошибки, баги, вопросы - страница 1890
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Все верно, нельзя приводиться снизу вверх, только сверху вниз.
В смысле нельзя приводить от базового класса к потомку?
Да, в случае когда на базовом не лежит реально сконструированный потомок.
Все верно, нельзя приводиться снизу вверх, только сверху вниз. Это ради безопасности.
Да.
Ренат, вы в курсе что такое 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); // эта строка не будет выполнена
}
Конечно.
Точно? Потому что dynamic_cast чаще всего как раз нужен для приведения снизу вверх, от родителя к потомку.
Мало того, в MQL он отлично приводит снизу вверх даже в том случае когда не должен:
Вы посмотрите на обсуждаемый кусок кода MQL5.
Да, он не должен работать, и выше уже объяснили почему, но совсем не потому что каст снизу вверх невозможен.
если мы приведем указатель сверху вниз, т.е. к родителю, после чего передадим указатель куда нить в другую область видимости, то там будут доступны поля потомка?
Да, вот пример, демонстрирующий ваш вопрос:
и вывод:Сначала проверяем неразрешенный кастинг снизу вверх и получаем NULL. Все верно.
Потом создаем объект CLASS2, присваиваем ссылку на него родительскому классу (тут важно понять, что в динамике среда знает, что исконный тип объекта CLASS2 - это хранится в его метаинформации). Далее (как раз ваш вопрос) динамически кастим (с проверкой права преобразования на основе метаинформации исходного объекта) из ссылки CLASS1 в CLASS2.
Проверяем результат кастинга и прописываем в переменную i = 1. В финале выводим значение i, обращаясь к исходно созданному объекту.
Все работает верно и по спецификации (включая dynamic_cast спеку самого C++).
Точно? Потому что dynamic_cast чаще всего как раз нужен для приведения снизу вверх, от родителя к потомку.
Мало того, в MQL он отлично приводит снизу вверх даже в том случае когда не должен:
Точно:
Не забывайте обновляться на последние билды. Я сейчас тестируюсь на 1598, который выкладывался недавно в виде зипов в этой ветке вроде.
Не забывайте обновляться на последние билды.
Да, старый билд.
Все верно, нельзя приводиться снизу вверх, только сверху вниз. Это ради безопасности.