Защо размерът на производен клас при множествено наследяване не включва собствен виртуален указател?

#include<iostream>

using namespace std;

class A
{
    virtual void fun() {}
};

class B
{
    virtual void fun2() {}
};
class C : virtual public  A, virtual public B
{
    public:
        virtual void fun3() {}
};


int main()
{

    /**
     * why is the size of C 16 and not 24?
     */
    cout<<sizeof(A)<<" "<<sizeof(B)<<" "<<sizeof(C);

    return 0;
}

Объркан съм защо размерът на C е 16, а не 24. Ако той наследява виртуалните указатели от клас A и B, тогава защо няма собствен виртуален указател?


person Yueyang Pan    schedule 30.06.2020    source източник
comment
Направете клас с 1 функция, след това клас с 10 функции... Има ли разлика в размера? ;) godbolt.org/z/_fNBBA   -  person ChrisMM    schedule 30.06.2020
comment
Най-вероятно е оптимизиран.   -  person Michael Chourdakis    schedule 30.06.2020
comment
Мисля, че клас поставя всички свои атрибути / функции в частни по подразбиране. Сигурни ли сте, че клас C има достъп до функциите на родителите си?   -  person Sunchock    schedule 30.06.2020
comment
@Sunchock, независимо дали има достъп до тях или не, те все още са там   -  person 463035818_is_not_a_number    schedule 30.06.2020
comment
Това отговаря ли на въпроса ви? Цена на паметта на таблицата с виртуални функции на C++   -  person user1810087    schedule 30.06.2020
comment
@idclev463035818 Прав си, но се чудех дали това не играе върху оптимизацията и изведнъж може би крайният размер   -  person Sunchock    schedule 30.06.2020
comment
Допълнение: Въпросът може да означава нещо различно, като: Ако C наследява указатели към vtable от A и B и има указател към собствената си vtable, защо размерът не е 3 указателя (24 байта в това случай). Поради това причината е, че компилаторът може да разшири наследена vtable, като по този начин клас C все още има само 2 указателя към vtables, A и B, но един от тях има добавена друга виртуална функция (fun3). Източник: как да се определи размерът на класа с виртуални функции?   -  person user1810087    schedule 30.06.2020
comment
Компилаторът вероятно организира vtables по по-умен начин от вас. Вероятно разпознава, че и двете A и B имат една единствена виртуална функция и прибира указателя за fun3() в свободно пространство в една или и двете от наследените vtables. В крайна сметка кодът, който използва C (например извиква object->fun3(), където object сочи към екземпляр на C или клас, извлечен от C), има видимост, че C има две бази, всяка от които има само една виртуална функция.   -  person Peter    schedule 30.06.2020
comment
Това се управлява от стандарта ABI, а не от C++. Вижте Категория 3: Само виртуални бази в itanium-cxx-abi. github.io/cxx-abi/abi.html#vtable   -  person Maxim Egorushkin    schedule 30.06.2020
comment
FWIW, не мисля, че виртуалното наследяване е правилно тук. Виртуалното наследяване обикновено помага при проблема с диамантите което не е точно това, което правите тук. Мисля, че вместо това искате нормално наследство.   -  person    schedule 01.07.2020