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

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

【пример】

class B0
{
    
    
public:
	B0(int v):v0(v){
    
    }//非默认构造函数
	int v0;
	void fun0()
	{
    
    
		cout << "基类B0的成员" << endl;
	}
};

class B1 :virtual public B0
{
    
    
public:
	B1(int v):B0(v){
    
    }//非默认构造函数
	int v1;
};

class B2 :virtual public B0
{
    
    
public:
	B2(int v) :B0(v) {
    
    }//非默认构造函数
	int v2;
};

class D :public B1, public B2
{
    
    
public:
	D(int v):B0(v),B1(v),B2(v){
    
    }//非默认构造函数
	int v;
	void fun()
	{
    
    
		cout << "派生类D的成员" << endl;
	}
};

int main()
{
    
    
	D d(1);
	d.v0 = 2;
	d.fun0();
	return 0;
}

Результаты выполнения:
вставьте сюда описание изображения
Анализ:

При создании D-объекта d через список инициализации конструктора из D вызывается не только конструктор B0() виртуального базового класса, инициализируется член v0, унаследованный от B0, но и непосредственный базовый класс B1 и The конструкторы B1() и B2() класса B2, а списки инициализации B1() и B2() также имеют инициализацию базового класса B0. Таким образом, v0, унаследованный от виртуального базового класса, инициализируется 3 раза?

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

Например, B0 в приведенном выше коде является виртуальным базовым классом производных классов B1 и B2, а объект d самого дальнего производного класса D, созданный в основной функции, содержит член v0, унаследованный от виртуального базового класса. , виртуальный базовый класс B0 Member v0 инициализируется конструктором наиболее удаленного производного класса D путем вызова конструктора виртуального базового класса B0. В это время вызовы других базовых классов B1 и B2 производного класса D к конструктору виртуального базового класса B0 автоматически игнорируются.

Подведем итог:

Общая последовательность построения объекта класса:

(1) Если класс имеет прямой или косвенный виртуальный базовый класс, сначала выполните конструктор в виртуальном базовом классе.
(2) Если у класса есть другие базовые классы, их конструкторы выполняются в том порядке, в котором они указаны в списке объявления наследования, но в процессе построения конструкторы их виртуальных базовых классов больше не выполняются.
(3) Инициализировать вновь добавленные объекты-члены в производном классе в том порядке, в котором они появляются в определении класса. Для объекта-члена типа класса, если он появится в списке инициализации конструктора, будет выполнен конструктор с указанными в нем параметрами, если он не появится, будет выполнен конструктор по умолчанию; для объекта-члена базового тип данных, если он появляется в конструкторе В списке инициализации использовать указанное в нем значение для присвоения его начального значения, иначе ничего не делать.
(4) Выполнить тело функции конструктора.

추천

출처blog.csdn.net/NuYoaH502329/article/details/132144243