Оптимизация пустой базы - это здорово. Тем не менее, он имеет следующие ограничения:
Оптимизация пустой базы запрещена, если один из пустых базовых классов также является типом или базой типа первого не статического члена данных, поскольку два базовых подобъекта одного типа должны иметь разные адреса в представлении объекта. самого производного типа.
Чтобы объяснить это ограничение, рассмотрим следующий код. Не static_assert
удастся. Принимая во внимание, что изменение Foo
или Bar
наследования вместо Base2
этого предотвратит ошибку:
#include <cstddef>
struct Base {};
struct Base2 {};
struct Foo : Base {};
struct Bar : Base {
Foo foo;
};
static_assert(offsetof(Bar,foo)==0,"Error!");
Я полностью понимаю это поведение. Чего я не понимаю, так это того, почему существует такое поведение . Это было очевидно добавлено по причине, так как это явное дополнение, а не недосмотр. Что является обоснованием для этого?
В частности, почему два базовых подобъекта должны иметь разные адреса? Выше, Bar
является типом и foo
является переменной-членом этого типа. Я не понимаю, почему базовый класс имеет Bar
значение для базового класса типа foo
или наоборот.
Действительно, я, если что-нибудь, я ожидал бы, что &foo
это то же самое, что и адрес Bar
экземпляра, содержащего его, - как это требуется в других ситуациях (1) . В конце концов, я не делаю ничего сложного с virtual
наследованием, базовые классы пусты независимо, и компиляция с Base2
показывает, что в этом конкретном случае ничего не ломается.
Но ясно, что это рассуждение как-то неверно, и есть другие ситуации, когда это ограничение будет необходимо.
Допустим, ответы должны быть для C ++ 11 или новее (в настоящее время я использую C ++ 17).
(1) Примечание: EBO был обновлен в C ++ 11 и, в частности, стал обязательным для StandardLayoutType
s (хотя Bar
, выше, это не a StandardLayoutType
).
Base *a = new Bar(); Base *b = a->foo;
сa==b
, ноa
иb
явно разные объекты (возможно , с разными переопределяет виртуальный метод).