C++ Виртуальное наследование памяти

Макеты памяти виртуального наследования

Я пытаюсь полностью понять, что происходит под капотом в памяти с виртуальным наследованием и vTables / vPtrs, а что нет.

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

Вот два примера на картинке, и я просто хочу знать, верны ли мои представления о разметке памяти.

Пример 1:

class Top { public: int a;  };
class Left : public virtual Top {  public: int b; };
class Right : public virtual Top { public: int c; };
class Bottom : public Left, public Right { public:  int d; };

Пример 2:

То же, что и выше, но с:

class Right : public virtual Top {
public:
    int c;
    int a;  // <======= added this
};

1 ответ

Стандарт C++ мало говорит о макете объекта. Виртуальные таблицы функций (vtables) и виртуальные базовые указатели даже не являются частью стандарта. Таким образом, вопрос и ответы могут только иллюстрировать возможные реализации.

Беглый взгляд на ваш рисунок, кажется, показывает правильное расположение.

Вас могут заинтересовать следующие ссылки:

Изменить: наследует ли нижний Right::a или же Left::a?

В вашем тесте 2, Right а также Left иметь общего родителя Top, Таким образом, есть только один подобъект Top в Bottomи, следовательно, существует только один и тот же Top::a,

Интересно, что вы представили в своем тесте 2 участника a в Right, Это a который отличается от a унаследованный от Top, Это отдельный член, и просто имеет то же имя, что и другая мембрана "по стечению обстоятельств". Так что, если вы получите доступ a через Right, Right::a прячет Top::a (что, кстати, также Bottom::Top::a, Right::Top::a, Left::Top::a). В этом случае bottom.a означает Right::a не из-за расположения объекта, а из-за правил подстановки имен (и скрытия). И это не зависит от реализации: оно стандартно и переносимо.

Вот вариант для вашего теста 2, чтобы продемонстрировать ситуацию:

int main() {
    Bottom bottom; 
    bottom.a = 7; 
    cout << bottom.Top::a << endl << bottom.Left::Top::a << endl;
    cout << bottom.Right::Top::a << endl << bottom.Left::a << endl;
    cout << bottom.Right::a << endl <<endl;
    bottom.Right::a = 4; 
    bottom.Left::a = 3; 
    cout << bottom.Top::a << endl << bottom.Left::Top::a << endl;
    cout << bottom.Right::Top::a << endl << bottom.Left::a << endl;
    cout << bottom.Right::a << endl <<endl;

    cout << "And the addresses are: " << endl; 
    cout << " Bottom:       " << (void*)&bottom << endl; 
    cout << " Top:          " << (void*)static_cast<Top*>(&bottom) << endl;
    cout << " Left:         " << (void*)static_cast<Left*>(&bottom) << endl;
    cout << " Right:        " << (void*)static_cast<Right*>(&bottom) << endl;
    cout << " Top::a:       " << (void*)&bottom.Top::a << endl;
    cout << " Left::Top::a: " << (void*)&bottom.Left::Top::a << endl;
    cout << " Right::Top::a:" << (void*)&bottom.Right::Top::a << endl;
    cout << " Left::a:      " << (void*)&bottom.Left::a << endl;
    cout << " Rigth::a:     " << (void*)&bottom.Right::a << endl;
}; 
Другие вопросы по тегам