Ответ 1
Каковы конкретные проблемы, которые следует избегать с ограничениями, налагаемыми этим пунктом 12.7p3 (см. первую часть параграфа ниже)?
Проблемы связаны с тем, что в какой-то момент виртуальные указатели (к виртуальной таблице или виртуальным базовым классам) должны быть инициализированы для производного класса. Это инициализация, которая возникает во время "списка инициализации" (т.е. До начала тела конструктора), как правило, сразу после создания базового класса (например, после того, как построен базовый класс B, указатель виртуальной таблицы и, возможно, виртуальный базовый указатель для класса X, а затем элементы данных инициализируются, а затем начинается тело конструктора). В общем случае выполнение up-cast перед инициализацией этих указателей приведет к поведению undefined либо потому, что требуемый поиск указателя не может быть выполнен для виртуальной базы, либо указатель виртуальной таблицы не будет корректно установлен для виртуальных функций правильно называется.
В примере, показанном в 12.7p3 (см. ниже), почему X (это) считается определенным? Это потому, что X не находится на пути E C D B A?
Потому что конструкторы базового класса вызывают в порядке их появления в объявлении класса (т.е. struct E : C, D, X {
). Так как базовые классы C и D построены, их общий виртуальный базовый класс A, безусловно, также построен. И поскольку X
не наследует от класса A
, это означает, что в данный момент существует полностью построенный и недвусмысленный путь при выполнении cast из класса E
в класс A
. Вот почему эта строка четко определена.
Правильно ли говорить, что множество всех прямых и косвенных оснований X, упомянутых выше, не включает B, и из-за этого код ниже хорошо определен, несмотря на то, что Base является прямой базой Derived и еще не началось?
Я не уверен, что следую вашим объяснениям, но могу вам сказать, что код, который вы показали, не определен. При вызове конструктора Base
путем отбрасывания Derived* this
до Base*
объект базового класса в производном классе еще не сконструирован, и, таким образом, литье undefined.
Единственный способ, которым этот код мог бы иметь смысл, - это отсутствие виртуальных функций или виртуальных базовых классов, вовлеченных в иерархию, и в этом случае такой код не понадобится, поскольку указатель this
для базового класса уже отправлен неявным образом в конструктор базового класса.