在 C++ 中,继承是一种面向对象编程的重要机制,它允许一个类(子类或派生类)继承另一个类(父类或基类)的属性和方法。继承能够实现代码复用和扩展已有类的功能。下面我将全面介绍继承的概念、继承的语法规则、对象模型、特殊关系以及多继承和虚继承的知识点,并通过一个简单的代码示例来展示这些概念。
1. 基本概念
- 基类(父类):被继承的类。
- 派生类(子类):继承了基类的类。
- 继承的语法:
2. 继承的类型
C++ 支持三种继承方式:
- Public 继承:基类的
public
成员在派生类中保持public
,基类的protected
成员在派生类中变为protected
,private
成员不能在派生类中访问。 - Protected 继承:基类的
public
和protected
成员在派生类中变为protected
。 - Private 继承:基类的
public
和protected
成员在派生类中变为private
。
3. 对象模型
- 构造函数和析构函数:派生类对象的创建和销毁过程先调用基类的构造函数和析构函数,再调用派生类的构造函数和析构函数。
- 内存模型:派生类对象包含了基类对象的内存空间,派生类对象可以通过
this
指针访问基类的成员。
4. 名字遮蔽与类作用域
在派生类中,如果定义了与基类相同名称的成员函数或变量,基类的成员会被遮蔽。可以通过 BaseClass::member
的方式显式调用基类的成员。
5. 继承的特殊关系
- 基类指针和派生类对象:基类的指针或引用可以指向派生类对象,这是多态的基础。
- 基类指针的限制:通过基类指针只能调用基类中定义的方法,而不能调用派生类新增的方法。
- 派生类对象赋值给基类对象:此时,非基类的成员会被舍弃。
6. 多继承与虚继承
- 多继承:C++ 支持一个类从多个基类继承。语法为:
class DerivedClass : public BaseClass1, public BaseClass2 {
// DerivedClass 继承了 BaseClass1 和 BaseClass2
};
虚继承:用于解决多继承中的菱形继承问题(基类被多次继承,导致数据冗余)。使用虚继承可以保证基类只会被派生类继承一次:
7. 解决二义性问题
你可以通过作用域解析运算符明确指出要调用哪个基类的函数。
8. 虚继承解决菱形继承问题
多重继承中还有另一种常见的继承问题——菱形继承,即当一个类继承自多个基类,而这些基类又继承自同一个类时,就可能导致重复继承。为了解决这个问题,可以使用虚继承。
菱形继承示例:
使用虚继承解决菱形继承问题:
通过将 Mammal
和 Bird
对 Animal
的继承声明为虚继承,可以确保 HybridPet
只继承一份 Animal
的成员,解决了菱形继承中的二义性问题。
总结
- 多重继承中的二义性可以通过作用域解析运算符
::
来解决。 - 菱形继承问题可以通过虚继承来解决,确保派生类只继承基类的一份成员。
- 在多重继承中,明确指定基类的方法或成员访问路径,能够有效避免继承中的模糊性问题。
9. 继承的设计原则
- Liskov 替换原则:派生类对象可以替代基类对象,而不会影响程序的正确性。这是良好继承设计的一个重要原则。
- 避免滥用继承:并不是所有情况下都需要使用继承。如果两个类之间并不是“is-a”(是一个)的关系,可以考虑组合(has-a)而非继承。