13-4静态联编与动态联编

静态联编与动态联编

在C++中,一个函数名对应哪一个函数代码块会因为函数重载而产生问题。为了解决这个问题,在函数编译时会对函数名进行修饰,来保证函数重载后的每一个函数的独立性。这称为静态联编。

然而,虚函数的出现使静态联编不能在编译时识别对应函数,因此必须在程序运行时选择正确的函数代码。这称为动态联编。

按值传递的函数将派生类的部分数据转化为基类给函数使用

13.4.1指针和引用类型的兼容性

向上强制转换和向下强制转换

向上强制转换:将派生类转换成基类,无需显式类型转换

向下强制转换:将基类转换为派生类,必须显式类型转换,否则不被允许

为了保证隐式向上强制转换,需要使用动态联编

13.4.2虚成员函数和动态联编

默认静态联编的原因

效率更高、一些基类的函数没必要重新定义增加工作量

虚函数的工作原理

编译器给每个对象添加一个隐藏成员,里面保存了一个指向函数地址数组的指针(即一个指针,指向一系列函数),这被称为虚函数表。里面存储了虚函数的地址。

一般基类声明中带有virtual关键字的函数地址被存入数组,如果派生类提供了虚函数的新定义,则将取代这个函数地址。如果派生类并没有提供虚函数定义,则使用原始版本的函数。

虚函数的成本

1.对象空间增大,增加量为存储函数的空间

2.对于每个类,编译器创建一个虚函数地址表

3.对于每个函数调用,都需要进行一个额外操作,即在表中查找地址。

13.4.3虚函数的注意事项

1.构造函数不能是虚函数

2.析构函数应当是虚函数

3.友元不能是虚函数,但可以通过调用虚函数来实现

4.重新定义将隐藏基类原方法(包含多个重载版本的同名方法),而不是生成两个(根据参数判断的)重载版本

这引出两个注意点:

1.尽量保证继承的虚方法与原方法原型一致

2.如果基类有多个版本的重载虚函数,应当在派生类中定义相同数量对应版本的虚函数,防止一个派生虚函数隐藏所有基类版本引发的问题。