Накладные расходы на наследование С++ без виртуальных функций

В С++ какие служебные данные (память/процессор) связаны с наследованием базового класса, который не имеет виртуальных функций? Это так же хорошо, как прямая копия + вставка членов класса?

class a
{
public:
    void get();
protected:
    int _px;
}

class b : public a
{

}

по сравнению с

class a
{
public:
    void get();
protected:
    int _px;
}

class b
{
public:
    void get();
protected:
    int _px;

}

Ответы

Ответ 1

При использовании наследования по сравнению с копией и прошлым могут возникнуть небольшие издержки памяти (из-за заполнения), рассмотрите следующие определения классов:

struct A
{
  int i;
  char c1;
};

struct B1 : A
{
  char c2;
};


struct B2
{
  int i;
  char c1;
  char c2;
};

sizeof (B1), вероятно, будет 12, тогда как sizeof (B2) может быть просто 8. Это связано с тем, что базовый класс A дополняется отдельно до 8 байтов, а затем B1 снова заполняется до 12 байтов.

Ответ 2

Для компиляции потребуется немного больше времени, и дополнительных затрат времени выполнения не будет. С точки зрения оптимизатора не виртуальные методы такие же, как и процедуры - их можно вызывать, используя только их адрес памяти, без накладных расходов из таблицы виртуальных методов.

Ответ 3

Если вы забудете виртуальное наследование, наличие базового класса эквивалентно памяти и производительности, то есть иметь член того же класса. Исключено, что иногда это может быть даже лучше (например, пустой класс имеет размер как минимум один, но с пустым базовым классом часто может не иметь накладных расходов).

Ответ 4

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

Компилятор будет генерировать прямой вызов кода, реализующего каждую не виртуальную функцию-член, поэтому нет накладных расходов.

Ответ 5

На самом деле, он не только увеличил память базовым классом. Подробнее о здесь в С++ FAQ