Даункастинг с использованием "static_cast" в C++

Рассматривать:

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();
}

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

3 ответа

Решение

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

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

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

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

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

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

Другие вопросы по тегам