我对两个版本的代码有一个疑问。
唯一的不同是在父类之间切换虚拟关键字。
有什么原因会发生这种情况吗?
版本一:
#include<iostream>
using namespace std;
class Person {
public:
Person(int x) { cout << "Person::Person(int ) called" << endl; }
Person() { cout << "Person::Person() called" << endl; }
};
class Faculty : public Person {
public:
Faculty(int x):Person(x) {
cout<<"Faculty::Faculty(int ) called"<< endl;
}
};
class Student : virtual public Person {
public:
Student(int x):Person(x) {
cout<<"Student::Student(int ) called"<< endl;
}
};
class TA : public Faculty, public Student {
public:
TA(int x):Student(x), Faculty(x), Person(x) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
版本的输出:Person::Person(int)被称为
Person::Person(int)被称为
Faculty::Faculty(int)被称为
学生::学生(int)叫
TA::TA(int)称为
第二版:
#include<iostream>
using namespace std;
class Person {
public:
Person(int x) { cout << "Person::Person(int ) called" << endl; }
Person() { cout << "Person::Person() called" << endl; }
};
class Faculty : virtual public Person {
public:
Faculty(int x):Person(x) {
cout<<"Faculty::Faculty(int ) called"<< endl;
}
};
class Student : public Person {
public:
Student(int x):Person(x) {
cout<<"Student::Student(int ) called"<< endl;
}
};
class TA : public Faculty, public Student {
public:
TA(int x):Student(x), Faculty(x), Person(x) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
输出为:Person::Person(int)被称为
Faculty::Faculty(int)被称为
Person::Person(int)被称为
学生::学生(int)叫
TA::TA(int)称为
最佳答案
类的初始化顺序基于在类的基类说明符列表中声明的顺序:
对于每个初始化的对象,此过程将递归重复。
对于第一个示例:
TA
是派生最多的类,因此首先初始化其Person
虚拟基础对象。Person
的构造函数主体运行并打印其消息。 Faculty
是第一个声明的基类,因此接下来对其进行初始化。Faculty
具有一个非虚拟基类Person
,因此它初始化了自己的Person
子对象。Person
的构造函数主体运行并打印其消息Faculty
的构造函数主体运行并打印其消息Student
是下一个基类,因此接下来将对其进行初始化。Student
不是派生最多的类,因此它没有获得自己的Person
子对象进行初始化。 Student
的构造函数主体运行并打印其消息TA
的构造函数主体运行并打印其消息结果是,构造函数的主体按以下顺序执行:
Person
Person
Faculty
Student
TA
对于第二个示例:
TA
是派生最多的类,因此首先初始化其Person
虚拟基础对象。Person
的构造函数主体运行并打印其消息。 Faculty
是第一个声明的基类,因此接下来对其进行初始化。Faculty
不是派生最多的类,因此它没有获得自己的Person
子对象进行初始化。 Faculty
的构造函数主体运行并打印其消息Student
是下一个基类,因此接下来将对其进行初始化。Student
具有一个非虚拟基类Person
,因此它初始化了自己的Person
子对象。Person
的构造函数主体运行并打印其消息Student
的构造函数主体运行并打印其消息TA
的构造函数主体运行并打印其消息结果是,构造函数的主体按以下顺序执行:
Person
Faculty
Person
Student
TA
请注意,在两种情况下,都有两个
Person
子对象。为了使Faculty
和Student
共享一个Person
子对象,两者都必须从Person
继承,即:class Person {
public:
Person(int x) { cout << "Person::Person(int) called" << endl; }
Person() { cout << "Person::Person() called" << endl; }
};
class Faculty : virtual public Person {
public:
Faculty(int x) : Person(x) {
cout<<"Faculty::Faculty(int) called"<< endl;
}
};
class Student : virtual public Person {
public:
Student(int x) : Person(x) {
cout<<"Student::Student(int) called"<< endl;
}
};
class TA : public Faculty, public Student {
public:
TA(int x) : Student(x), Faculty(x), Person(x) {
cout<<"TA::TA(int) called"<< endl;
}
};
在这种情况下,逻辑将是:TA
是派生程度最高的类,因此其Person
虚拟基础对象首先被初始化。Person
的构造函数主体运行并打印其消息。 Faculty
是第一个声明的基类,因此接下来对其进行初始化。Faculty
不是派生最多的类,因此它没有获得自己的Person
子对象进行初始化。 Faculty
的构造函数主体运行并打印其消息Student
是下一个基类,因此接下来将对其进行初始化。Student
不是派生最多的类,因此它没有获得自己的Person
子对象进行初始化。 Student
的构造函数主体运行并打印其消息TA
的构造函数主体运行并打印其消息结果是类的构造函数体按以下顺序执行:
Person
Faculty
Student
TA
关于c++ - 两个父类的构造函数的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62557119/