Так что невозможно обратное приведение с помощью static_cast
с виртуальным наследованием, но как можно сделать следующий вентиляционный:Как использовать static_cast с виртуальным наследованием?
class Base {...};
class Derived : public virtual Base {...};
...
Derived *d = new Derived();
Base *b = static_cast<Base*>(d);
макет памяти объекта:
[ derived part | base part ]
Я знаю, что приведение к базовому типу считается «безопасно», но как компилятор может узнать смещение базового под-объекта во время компиляции, когда наследование виртуально? Использует ли static_cast
vtable
?
Это особенно сбивает с толку, когда мы что-то вроде этого (обратите внимание, что это не виртуальные):
class Third : public Derived {...};
...
Derived *d = new Third(); // non-virtual upcast, no offset will be added
Base *b = static_cast<Base*>(d);
На этот раз я использовал ту же самую static_cast
линию, но смещение к Base
подъобекта отличается!
Разметка памяти объекта:
[ derived part | third part | base part ]
Так как это может быть определено во время компиляции, если это зависит от фактического динамического типа объекта d
указывает на?
Это, как правило, из того, что я знаю, что смещения хранятся в таблице vtable. Однако это не отвечает на вопрос о том, как это делается статически во время компиляции. Если вы посмотрите на два случая, которые я предусмотрел, возникает вопрос, какой vtable имеет правильный сдвиг? На какой компилятор должен смотреть виртуальный стол Derived или vtable? Очевидно, что 2 смещения в vtables различны, и выбор правой таблицы vtable зависит от типа времени выполнения. Вот почему я не понимаю, как это делается статически. –
«Статический» в 'static_cast' не означает, что это делается во время компиляции! Это просто означает, что компилятор может статически определять, где найти информацию во время компиляции: например, он знает, где искать смещение в таблице vtable или где находится встроенный указатель на базу (в зависимости от того, как виртуальное наследование реализуется). Он не будет искать соответствие некоторого класса в vtable, как 'dynamic_cast'. –
Итак, вы говорите, что у static_cast есть динамический аспект, я вижу. По этой логике почему static_cast не может преуменьшать виртуальное наследование? –