多重继承是C++的一项功能,其中一个类可以从多个类中继承。
继承类的构造函数以它们继承的相同顺序被调用。例如,在下面的程序中,在A的构造函数之前调用B的构造函数。
#include
using namespace std;
class A
{
public:
A() { cout << "A's constructor called" << endl; }
};
class B
{
public:
B() { cout << "B's constructor called" << endl; }
};
class C: public B, public A // Note the order
{
public:
C() { cout << "C's constructor called" << endl; }
};
int main()
{
C c;
return 0;
}
输出:
B's constructor called
A's constructor called
C's constructor called
析构函数以与构造函数相反的顺序调用。
钻石问题
当一个类的两个超类具有一个共同的基类时,就会发生钻石问题。例如,在下图中,TA类获取Person类的所有属性的两个副本,这会造成歧义。
例如,考虑以下程序。
#include
using namespace std;
class Person {
// Data members of person
public:
Person(int x) { cout << "Person::Person(int ) called" << endl; }
};
class Faculty : public Person {
// data members of Faculty
public:
Faculty(int x):Person(x) {
cout<<"Faculty::Faculty(int ) called"<< endl;
}
};
class Student : public Person {
// data members of Student
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) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
Person::Person(int ) called
Faculty::Faculty(int ) called
Person::Person(int ) called
Student::Student(int ) called
TA::TA(int ) called
在上面的程序中,“ Person”的构造函数被调用了两次。当对象“ ta1”被破坏时,“ Person”的析构函数也将被调用两次。因此,对象“ ta1”具有“人”所有成员的两个副本,这会造成歧义。解决这个问题的方法是’virtual’关键字。我们将“教师”和“学生”类作为虚拟基类,以避免在“ TA”类中使用“人”的两个副本。例如,考虑以下程序。
#include
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 : 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) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
输出:
Person::Person() called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called
在上面的程序中,“ Person”的构造函数被调用一次。在上面的输出中要注意的一件事是, ‘Person’的默认构造函数称为。当我们使用’virtual’关键字时,即使父类显式调用参数化的构造函数,默认情况下也会调用祖父母类的默认构造函数。
如何调用“ Person”类的参数化构造函数?构造函数必须在“ TA”类中调用。例如,请参见以下程序。
#include
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 : 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 ) called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called
通常,不允许直接调用祖父母的构造函数,而必须通过父类进行调用。仅在使用“ virtual”关键字时才允许使用。
作为练习,预测以下程序的输出。
问题1
#include
using namespace std;
class A
{
int x;
public:
void setX(int i) {x = i;}
void print() { cout << x; }
};
class B: public A
{
public:
B() { setX(10); }
};
class C: public A
{
public:
C() { setX(20); }
};
class D: public B, public C {
};
int main()
{
D d;
d.print();
return 0;
}
问题2
#include
using namespace std;
class A
{
int x;
public:
A(int i) { x = i; }
void print() { cout << x; }
};
class B: virtual public A
{
public:
B():A(10) { }
};
class C: virtual public A
{
public:
C():A(10) { }
};
class D: public B, public C {
};
int main()
{
D d;
d.print();
return 0;
}
要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程” 。