Что такое почти пустой класс?

Скомпилируйте следующий класс

class Interface
{
  virtual void doIt() = 0;
  virtual ~Interface() = 0;
};

inline Interface::~Interface() {}

используя gcc -fdump-class-hierarchy.

gcc излучает

Class Interface
   size=4 align=4
   base size=4 base align=4
Interface (0x1a779c0) 0 nearly-empty
    vptr=((& Interface::_ZTV9Interface) + 8u)

Каково значение «почти пустого»? Что это значит?


person Tobias    schedule 20.07.2009    source источник
comment
Не связано, но... Не делайте виртуальный деструктор таким чистым виртуальным, как вы предоставляете реализацию.   -  person Naveen    schedule 20.07.2009
comment
Не думаю, что это особенно хороший совет. Чисто виртуальные деструкторы — это обычное сокращение для того, чтобы сказать, что класс является абстрактным, и они должны иметь реализацию.   -  person    schedule 20.07.2009
comment
@Naveen: Почему бы и нет? Любая чисто виртуальная функция может иметь реализацию.   -  person dalle    schedule 20.07.2009
comment
... и деструкторы должны иметь реализацию.   -  person dalle    schedule 20.07.2009


Ответы (4)


C++ ABI предоставляет определение "почти пустых" классов и интересное обсуждение того, как они влияют на построение vtable:

Класс, который содержит виртуальный указатель, но не содержит других данных, кроме (возможно) виртуальных баз. В частности, это:

  • не имеет нестатических членов данных, кроме битовых полей нулевой ширины,
  • не имеет прямых базовых классов, которые не были бы ни пустыми, ни почти пустыми, ни виртуальными,
  • имеет не более одного невиртуального, почти пустого прямого базового класса и
  • не имеет надлежащего базового класса, который является пустым, морально не виртуальным и имеет смещение, отличное от нуля.

Я столкнулся с этим, исследуя влияние почти пустых виртуальных баз на размер объекта, размер виртуальной таблицы и накладные расходы виртуальных вызовов.

person Trevor Robinson    schedule 29.06.2010

В C++ есть так называемая "оптимизация пустой базы". Если у класса нет членов, ему не нужно занимать место, когда он используется в качестве базового класса. Примером того, почему это важно, является std::unary_function<T, U>. Он существует, чтобы предоставить вам простой набор определений типов. Эти определения типов не должны влиять на размер вашего класса функторов.

Если у вас есть базовый класс с указателем vtable, этот указатель, скорее всего, можно использовать совместно с производным классом. Вы просто создаете виртуальную таблицу для производного класса, который добавляет свои собственные методы после методов базового класса.

Теперь вы можете получить аналогичный базовый класс «без дополнительных накладных расходов». По-видимому, GCC называет это «почти пустым».

person MSalters    schedule 20.07.2009
comment
Звучит правдоподобно. У вас есть ссылка, чтобы подтвердить это? - person Tobias; 20.07.2009

Я полагаю, это нужно для того, чтобы отличить его от «пустого», что вы получите, если скомпилируете класс вообще без членов. «почти пустой», по-видимому, означает, что у него есть vtable и ничего больше.

person Community    schedule 20.07.2009

У него есть только vtable, без полей данных.

person Daniel Earwicker    schedule 20.07.2009