Downcasting с использованием "static_cast" в С++

Рассмотрим:

class base
{
    base();
    virtual void func();
}

class derived : public base
{
    derived();
    void func();
    void func_d();
    int a;
}


main
{
    base *b = new base();
    sizeof(*b); // Gives 4.
    derived * d = static_cast<derived*>(b);
    sizeof(*d); // Gives 8- means whole derived obj size..why?
    d->func_d();
}

В приведенном выше коде я исказил базовый указатель, который указывает на базовый объект на указатель производного класса. Мне интересно, как производный указатель имеет весь производный объект класса. Я могу вызвать функцию производного класса (только в производном классе). Я не понял эту концепцию.

Ответ 1

Используя static_cast, чтобы отличить объект от типа, он фактически не имеет поведения undefined. Симптомы UB сильно различаются. Там нет ничего, что говорит, что UB не может позволить вызываемой функции-члена быть вызванным успешно (но там ничего, что гарантирует, что он будет, поэтому не рассчитывайте на него).

Вот правило для downcasting с использованием static_cast, найденного в разделе 5.2.9 ([expr.static.cast]) стандарта С++ (формулировка С++ 0x):

Значение типа "указатель на cv1 B", где B является типом класса, может быть преобразовано в prvalue типа "указатель на cv2 D", где D - это производный от класса из B, если существует допустимое стандартное преобразование из "указателя на D" в "указатель на B", cv2 является той же самой cv-квалификацией, что и более высокая cv-квалификация, чем cv1 и Bне является ни виртуальным базовым классом D, ни базовым классом виртуального базового класса D. Значение нулевого указателя преобразуется в значение нулевого указателя для типа назначения. Если значение prawue типа "указатель на cv1 B" указывает к B, который на самом деле является подобъектом объекта типа D, результирующий указатель указывает на охватывающий объект типа D. В противном случае результат приведения undefined.

Ответ 2

Единственный листинг, выполняющий проверку времени выполнения, dynamic_cast<>(). Если есть вероятность, что приведение не будет работать во время выполнения, то этот прилив должен использоваться.

Таким образом, отливка из leaf- > root (up casting) static_cast<>() отлично работает.
Но литье из root- > leaf (down casting) опасно и, по-моему, всегда должно выполняться с dynamic_cast<>(), так как будут зависимости от времени выполнения. Стоимость небольшая, но всегда стоит платить за безопасность.

Ответ 3

sizeof существует во время компиляции. Он не знает и не заботится о том, что во время выполнения ваш базовый объект не указывает на derived. Вы пытаетесь влиять на поведение во время компиляции с переменной времени выполнения, что принципиально невозможно.