23"); author.printDOB(); // 输出 Thomas 的出生日期
return0;
}
继承的概念
继承是面向对象编程的一个关键特性,允许我们创建一个新类(派生类)作为现有类(基类)的扩展。通过继承,派生类可以重用基类的功能,并在其基础上添加新的特性和行为。在 C++ 中,基类可以通过使用冒号(:)来声明,后跟访问修饰符(public, private 或 protected)以及基类的名字。
虚基类的介绍
在多继承的场景下,如果多个基类共同继承自同一个基类,不使用虚基类可能导致“菱形问题”(diamond problem),即派生类有多个路径去继承同一个基类,从而产生二义性。为了解决这个问题,C++ 提供了虚基类的概念。通过在基类声明前加上关键字 virtual,我们可以确保无论通过哪个基类路径,派生类只会有一个实例化的虚基类。
虚基类的构造函数调用
当一个类继承了虚基类,那么在派生类的构造函数中,必须显式地调用虚基类的构造函数。这是因为每个派生类的对象都只有一个虚基类的实例。如果不在派生类的构造函数成员初始化列表中显式调用虚基类的构造函数,编译器将默认调用其默认构造函数。这种机制确保了所有派生类都能正确初始化虚基类的部分。
继承的构造函数调用顺序
在 C++ 中,构造函数的调用顺序遵循以下原则:
1. 首先,调用最远派生类(即直接创建的对象所在的类)的构造函数。
2. 最远派生类的构造函数会负责调用其直接基类的构造函数,包括虚基类的构造函数。
3. 这个过程会一直持续到所有的基类都被初始化,包括虚基类。
例如,在多继承的继承结构中,如果类 A、B 和 C 分别继承自虚基类 D,而类 E 继承自 A 和 B,那么在创建 E 类的对象时,构造函数的调用顺序将是 D -> A -> B -> E。
总结
虚基类及其派生类构造函数是 C++ 多继承中的一个重要概念,它解决了多继承中的菱形问题,确保了类继承层次结构中的唯一性。在编写派生类时,必须注意在构造函数中显式调用虚基类的构造函数,以保证对象的正确初始化。理解这一机制对于编写复杂的、具有继承关系的 C++ 程序至关重要。