本文将通过三个经典示例程序,带你彻底理解:
-
多层继承的访问规则
-
多源继承的构造与析构顺序
-
菱形继承中的二义性问题
一,多层继承
概念
多层继承指 一个类继承另一个派生类,形成继承链,例如:
A → B → C
类 C
间接继承了 A
的成员。
示例代码:
cpp
#include <iostream>
using namespace std;
class A
{
public:
A() { cout << "A" << endl; }
~A() { cout << "~A" << endl; }
public:
void fun_A_public() { cout << "fun_A_public" << endl; }
protected:
void fun_A_protected() { cout << "fun_A_protected" << endl; }
private:
void fun_A_private() { cout << "fun_A_private" << endl; }
};
class B : public A
{
public:
B() { cout << "B" << endl; }
~B() { cout << "~B" << endl; }
public:
void fun_B_public() { cout << "fun_B_public" << endl; }
protected:
void fun_B_protected() { cout << "fun_B_protected" << endl; }
private:
void fun_B_private() { cout << "fun_B_private" << endl; }
};
class C : public B
{
public:
C() { cout << "C" << endl; }
~C() { cout << "~C" << endl; }
public:
void fun_C_public() { cout << "fun_C_public" << endl; }
protected:
void fun_C_protected() { cout << "fun_C_protected" << endl; }
private:
void fun_C_private() { cout << "fun_C_private" << endl; }
};
int main()
{
// 1. 在类外部通过类对象只能访问public成员
// 2. 对基类成员的访问由继承方式和原访问权限共同决定
// (1)只有基类的public成员,以public形式继承,那么派生来的对象在类外部才可以访问
// (2)除此之外的情况,派生来的对象在类外部都无法访问
C c;
c.fun_A_public();
c.fun_B_public();
c.fun_C_public();
return 0;
}
- 在类的内部,只能访问基类的public、protected成员,private无法访问
- 如果是多层继承的的话,那么子类对基类成员的访问,只看其直接父类中成员访问权限
- 父类成员在子类中存在的的访问权限,是由继承方式和原成员访问权限共同决定
理解方法:
- 如果看子类内部是否能访问,那么将继承关系的代码改为单继承来看。
- 如果看子类外部是否能访问,那么将继承关系的代码改为单个类来看
- 在改代码时,将父类中的代码复制到子类中,然后按照继承方式修改父类成员访问权限
运行结果:

结果分析
-
构造顺序:
A → B → C
-
析构顺序:
~C → ~B → ~A
-
访问权限:
-
类外部只能访问最终类对象中 public继承下来的public成员。
-
类内部可访问基类的
public
与protected
,不能访问private
。
-
二,多源继承
概念
多源继承(或称"多重继承")是指一个派生类从多个基类继承:
cpp
class C : public A, public B
这种设计可以让子类同时拥有多个基类的功能,但也可能带来复杂性。
示例代码:
cpp
#include <iostream>
using namespace std;
class A
{
public:
A(int n) { cout << "A" << endl; }
~A() { cout << "~A" << endl; }
};
class B
{
public:
B(int n) { cout << "B" << endl; }
~B() { cout << "~B" << endl; }
};
// 多源继承:构造顺序由继承列表顺序决定,而不是初始化列表顺序
class C : public A, public B
{
public:
C(int n) : B(n), A(n)
{
cout << "C" << endl;
}
~C() { cout << "~C" << endl; }
};
int main()
{
C c(5);
return 0;
}
输出结果:

结果分析
-
构造顺序
由继承列表顺序决定:
A → B → C
即使初始化列表写成
B(n), A(n)
,也无效。 -
析构顺序
与构造相反:
~C → ~B → ~A
-
注意点
-
构造顺序只与 类定义时的继承顺序 有关;
-
初始化列表顺序不会改变这一点;
-
若多个基类含有同名成员,会产生访问二义性。
-
三,菱形继承
概念
菱形继承是一种特殊的多重继承结构:

类 D
同时继承 B
和 C
,而 B
、C
又继承自 A
。
这会导致 D
中出现两个 A
子对象,从而引发 二义性问题。
示例代码:
cpp
#include <iostream>
using namespace std;
class A
{
public:
A() { cout << "A" << endl; }
~A() { cout << "~A" << endl; }
void fun_A() { cout << "fun_A" << endl; }
};
class B : public A
{
public:
B() { cout << "B" << endl; }
~B() { cout << "~B" << endl; }
void fun() { cout << "fun_B" << endl; }
};
class C : public A
{
public:
C() { cout << "C" << endl; }
~C() { cout << "~C" << endl; }
void fun() { cout << "fun_C" << endl; }
};
class D : public B, public C
{
public:
D() { cout << "D" << endl; }
~D() { cout << "~D" << endl; }
};
int main()
{
D d;
d.B::fun_A(); // 明确指定作用域
// d.fun_A(); // 错误:二义性,D 中存在两个 A 子对象
cout << sizeof(D) << endl;
return 0;
}
运行结果:

结果分析
-
类
D
拥有 两个独立的 A 子对象(来自 B 和 C)。 -
调用
fun_A()
时会出现二义性错误 ,需指定作用域:d.B::fun_A()
。 -
内存中
D
的大小包含了两个A
子对象的空间。
解决办法:虚继承
通过在 B
和 C
中使用 虚继承 ,可以让 D
只保留一个共享的 A
子对象:
cpp
class B : virtual public A { ... };
class C : virtual public A { ... };
此时 D
中只有一个 A
实例,二义性问题消失,内存占用也更小。
四、总结对比表

