Алгоритм поиска макета объекта некоторого класса в памяти в C ++ - PullRequest
1 голос
/ 02 июля 2019

Рассмотрим следующий код:

class A {
public:
    virtual ~A();
    virtual void foo();
};
class B : public A {
public:
    virtual ~B();
    virtual void foo();
};

Расположение объекта класса B в памяти выглядит следующим образом:

enter image description here

Трудно расположить объект некоторого класса в памяти, когда мы говорим о множественном наследовании, особенно когда мы говорим о наследовании с помощью diamond или когда мы говорим о виртуальном классе, таком как:

class E : public C, public virtual D, public virtual B {
public :
    E() {
        cout << "E::E()" << endl;
    }
    E(int x) : D(x) {
        cout << "E::E(int)" << endl;
    }
};

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

РЕДАКТИРОВАТЬ : Я получил следующий пример:

enter image description here

А расположение памяти в разделе решений таково:

enter image description here* * 1030

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

Ответы [ 3 ]

2 голосов
/ 02 июля 2019

Это расположение зависит от ABI, на который ориентирован ваш компилятор.Вы должны изучить документацию ABI, чтобы узнать, как классы должны быть расположены в памяти.

Например, GCC использует Itanium ABI .

0 голосов
/ 02 июля 2019

За исключением стандартных типов макетов, он определяется реализацией и, возможно, также не определен:

Для шаблонов множественного наследования вы можете использовать static_cast, чтобы выяснить, как это макет - хотя даже тогда нет гарантии: это выглядиткак это:

void* offsetToB = static_cast<B*>(static_cast<A*>(nullptr));

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: на это опасно полагаться.

0 голосов
/ 02 июля 2019

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

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

Мы начинаем с E. Он имеет не виртуальную C базу, виртуальную B базу и виртуальную D базу. У C есть виртуальный подобъект B, который становится указателем. Виртуальный B уже имеет указатель, который будет указывать на то же место, что и база C. Виртуальному D нужен указатель.

Это завершает не виртуальные базы E, но все еще существуют виртуальные базы, в которых еще нет хранилища.

Мы делаем B, который имеет не виртуальный A, и записываем смещение в E. Мы делаем D, который имеет не виртуальный B, который имеет не виртуальный A, и записываем смещение в E

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