Не полиморфный тип или зачем нам здесь виртуальные деструкторы? - PullRequest
0 голосов
/ 23 марта 2019

В настоящее время я изучаю динамическое приведение и, таким образом, я тестирую различные фрагменты кода.

Я протестировал приведенный ниже код с и без виртуальных деструкторов, отмеченных в (2), и обнаружил, что строка (3) верна, только если есть строка (2).Без этого код не компилируется.Но почему?Интересно, что строка (1) вообще не нужна.

struct A {
    virtual ~A() = default; \\ (1)
};
struct B {
    virtual ~B() = default; \\ (2)
};
struct D : A, B {};

B* pb = new D();
A* pa = dynamic_cast<A*>(pb); \\ (3)

1 Ответ

0 голосов
/ 23 марта 2019

В общем случае

dynamic_cast требуется для определения поведения во время выполнения.В зависимости от реального типа отлитого объекта он либо вернет nullptr, либо верный указатель целевого типа.

Чтобы это произошло во время выполнения, реализация C ++ должна иметь доступ к некоторой дополнительной информации о типе во время выполнения .И управление этой информацией требует выполнения некоторых дополнительных операций.Накладные расходы минимальны, но они существуют.

Динамическое приведение не всегда необходимо.Разработчик языка C ++ решил не создавать ненужных накладных расходов, если они не нужны.Поэтому, если вы не скажете, что полиморфизм необходим, компилятор постарается решить все вопросы с типами в максимально возможной степени во время компиляции.

Чтобы сказать, что полиморфизм и динамическая типизация необходимы, нужно иметь хотя бы одну виртуальную функцию-член в классе.

Ваш конкретный случай

Если вы очень хорошо знаете в своей программе, что тип исходного объекта совместим с типом целевого объекта, вы можете использовать static_cast, как объяснено здесь.

Но в вашем случае это не сработает, поскольку pb - это *B (статический тип), потому что в общем случае *B нельзя преобразовать в *A, поскольку оба типа совершенно не связаны,

Но *D (динамический тип) может быть приведен к *A ввиду его множественного наследования.И именно поэтому здесь необходимо dynamic_cast: чтобы отслеживать исходный D-тип объекта, на который указывает pb.А для этого необходимо, чтобы у класса была хотя бы виртуальная функция, как описано выше.

...