создание класса, наследуемого от виртуального класса

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

Например: (Выход равен 5)

#include <iostream> 
using namespace std;

struct A { 
public:  int myInt;  
 A():myInt(5) {} 
 A(int n): myInt(n) {} 
};  

class B : virtual public A { 
public: 
 B(int n):A(10) {}  B():A(10) {} 
};  

class C : virtual public A { 
public:  
C(int n):A(3*n) {} 
};  

class D : public B, public C {
 public:  
D(int n=90) : C(2*n), B(n) {} 
};  

int main() {  
D d(100);  
cout << d.myInt << endl;     
return 0; 
}

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

Но что происходит при построении «части A» C и B с точки зрения «единственного созданного экземпляра A». Я знаю, что сначала неявно вызывается конструктор A, так как есть конструктор по умолчанию), а потом уже все прямые базовые классы.

Я предполагаю, что при создании, например, части A C конструктор A не вызывается снова, поскольку он уже создан. Я прав?


person Alex Goft    schedule 14.09.2015    source источник


Ответы (2)


Но что происходит при построении «части A» C и B с точки зрения «единственного созданного экземпляра A». Я знаю, что сначала неявно вызывается конструктор A, так как есть конструктор по умолчанию), а потом уже все прямые базовые классы.

Это зависит от того, конструируется ли B или C сам по себе или как подобъект D. То, что вы говорите, верно, когда они построены как подобъекты объекта D. Это верно, поскольку конструктор D не имеет явного вызова ни одного из конструкторов A в списке инициализации.

Поскольку вы используете:

B(int n):A(10) {}  B():A(10) {} 

когда вы создаете B с помощью

B b;

A() не используется, но A(10) используется для создания подобъекта A.

Я предполагаю, что при создании, например, части A C конструктор A больше не вызывается, поскольку он уже создан. Я прав?

Да, ты прав.

person R Sahu    schedule 14.09.2015

Вы можете взглянуть на isocpp.org, а именно: "Еще раз: что это точный порядок конструкторов в ситуации множественного и/или виртуального наследования?", в котором говорится:

Самые первые исполняемые конструкторы — это виртуальные базовые классы в любом месте иерархии. Они выполняются в том порядке, в котором они появляются при обходе в глубину слева направо графа базовых классов, где слева направо относятся к порядку появления имен базовых классов.

После того, как все конструкторы виртуальных базовых классов завершены, порядок построения обычно следующий: от базового класса к производному классу. Детали легче всего понять, если представить, что самое первое, что компилятор делает в ctor производного класса, — это скрытый вызов ctor его невиртуальных базовых классов (подсказка: так на самом деле делают многие компиляторы). . Таким образом, если класс D наследует умножение от B1 и B2, сначала выполняется конструктор для B1, затем конструктор для B2, затем конструктор для D. Это правило применяется рекурсивно; например, если B1 наследуется от B1a и B1b, а B2 наследуется от B2a и B2b, то окончательный порядок будет B1a, B1b, B1, B2a, B2b, B2, D.

Обратите внимание, что порядок B1, а затем B2 (или B1a, а затем B1b) определяется порядком, в котором базовые классы появляются в объявлении класса, а не порядком, в котором инициализатор появляется в списке инициализации производного класса.

person Nicko Po    schedule 14.09.2015