- 派生类如果没有覆盖虚函数则会自动使用之前的定义。
- 一个类如果没有数据成员,C++编译器会自动插入一个char类型。这样保证了每个对象都有不同的地址。
- 基类和派生类会在同一个地方有VPTR(经常是对象开始的位置)。
- 虚函数调用需要两步复杂的汇编指令,而普通函数需要一步指令
- 如果想通过指针或引用调用虚函数,那么虚函数不能是内联函数。因为内联函数没有地址,而虚函数通过虚表中的函数地址调用。
- 抽象基类不能实例化,只是一个接口。
- 通过定义纯虚函数,我们告诉编译器在虚表中保留一个槽的位置,但不放入任何函数的地址。
- 纯虚函数显示声明了一个类的抽象性。
- 纯虚函数避免了值传递的函数调用(本意是想通过引用或者指针触发多态)。也避免了向上转型中值传递造成的裁剪。
- 纯虚函数可以有定义。这样的话,虚表中的槽仍然是空的,但是派生类中可以调用那个函数。(也就是在派生类中对应的那个槽填入了函数地址)
- 编译器为你创建的新类型创建一个虚表,在虚表中插入新的函数地址,如果你没有覆盖原来的函数,则函数地址是基类的函数地址。
- 因为编译器产生的代码使用数值偏移在虚表中选择虚函数,所以同名函数所在槽的位置在基类和派生类中是相同的。
- 编译器使用指向基类的指针时,只能调用基类的函数。(如果没有向下转型)
- 值传递时,编译器为基类使用拷贝构造函数,并初始化虚表指针指向基类的虚表。
- 对于14,你可以通过在基类中设置一个纯虚函数来避免裁剪。
- 对于构造函数,编译器会偷偷在其中插入代码来做以下几件事情 A)初始化虚表指针; B)检查this的值,因为operator new可能返回空指针; C) 调用基类构造函数; 构造函数的大小带来的损失可能会大于你节省的函数调用的开销,如果你调用了很多次内联构造函数,那么你的代码量可能会暴增哦。
- 你应该尽可能在初始化列表中初始化所有成员对象。
- 虚函数的机制在构造函数中不生效。(如果生效,那么你可能在调用一个使用派生类数据的虚函数,而那个数据还没有初始化。)
- 每个构造函数都会初始化虚表指针,所以虚表指针由最后的派生类决定。
- 在构造函数中调用虚函数会调用那个类的版本的虚函数。(前期绑定)
- 虚函数可以并且经常是虚函数。
- 你应该记住构造函数和虚函数是唯二的两个地方,我们调用一个函数,会引起整个系列函数的调用。
- 如果你创建一个纯虚的析构函数,你必须提供函数体,因为一个类层次中,所有的析构函数总会被调用。
- 基类的纯虚析构函数会强迫派生类覆盖析构函数,但基类的函数提仍然是析构的一部分。
- 一旦你在类中有了一个虚函数,你应该立马加上一个虚析构函数。
- 析构函数中调用虚函数也是调用那个类的版本的虚函数。
C++虚函数
最新推荐文章于 2023-02-10 20:35:41 发布