📜  C++中的多重继承

📅  最后修改于: 2021-05-30 10:00:51             🧑  作者: Mango

多重继承是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等的更多准备工作,请参阅“完整面试准备课程”