多重继承是C++的一个特性,其中类可以从多个类继承。
null
继承类的构造函数按继承的顺序调用。例如,在下面的程序中,B的构造函数在A的构造函数之前被调用。
#include<iostream> 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<iostream> 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”有两个“Person”所有成员的副本,这会导致歧义。 这个问题的解决方案是“虚拟”关键字 .我们将“教员”和“学生”作为虚拟基类,以避免在“TA”类中出现“人”的两个副本。例如,考虑下面的程序。
#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 : 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<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 : 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<iostream> 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<iostream> 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; } |
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写评论
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END