Страницы

Поиск по вопросам

воскресенье, 15 декабря 2019 г.

Запрещение кастинга виртуального базового класса

#cpp


Почему запрещён кастинг в следующем коде?

class Base
{
};

class Derived : virtual public Base
{
};

int main()
{
    Base *p = new Derived;
    static_cast(p);
    return 0;
}

    


Ответы

Ответ 1



Компилятор не может скастовать Base* к Derived*, потому что он не делает полный анализ кода, а значит не знает как именно расположены типы друг относительно друга. Если существуют только типы Base и Derived, то при касте Base* в Derived* надо добавить смещение в 0 байт, т.к. адреса Derived и Base совпадают. Однако компилятор допускает, что может существовать другие типы, например struct Derived2 : virtual Base { char x[1024]; }; struct MostDerived : virtual Derived2, Derived {}; И Base* p может указывать на объект этого типа. Тогда MostDerived выглядит в памяти так: смещение | что находится 0 | MostDerived 0 | Base 0 | Derived2 0 | char Derived2::x[1024] 1024 | Derived Виртуальный базовый класс Base, находится в Derived2, самом первом базовом классе MostDerived. Т.к. Base - это пустой базовый класс, он не занимает никакого места в памяти. После Derived2 будет располагаться Derived, уже без Base. По этому в этом случае при касте Base* в Derived* надо добавить смещение в 1024 байт. Т.к. компилятор не знает какое именно смещение надо использовать, он не может сделать такой static_cast. По этому для виртуальных базовых типов поддерживается только dynamic_cast, и то, только для типов в которых есть виртуальные функции.

Комментариев нет:

Отправить комментарий