// invalid assignment. mismatched pointer types
// ok
将选择哪种类型的对象。所以,编译器必须生成能够在程序运行时选择正确的虚方法的代码,这被称为动
态联编(dynamic binding),又称为晚期联编(late binding)。
知道虚方法的运行情况后,下面深入地探讨这一过程,首先介绍C++如何处理指针和引用类型的兼容性。
13.4.3 指针和引用类型兼容性
在C++中,动态联编与指针和引用调用的方法相关,从某种程度上说,这是由继承控制的。公有继承
建立is-u 关系的 种方法是如何处理指向对象的指针和引用。通常,C++不允许将·种类型的地址赋给另
种类型的指针,也不允许一种类型的引用指向另一种类型:
double x - 2.5:
int * pi = 6x:
long & rl = x: // invalid assignment. mismatched reference type
不过,正如您看到的,指向基类的引用或指针可以引用派生类对象,而不必进行显式类型转换。例如,
下面的初始化是允许的:
BrassPlus dilly ("Annie Dill", 493222, 2000) ;
Brass * pb = &dilly: // ok
Brass & rb = dilly:
将派生类引用或指针转换为基类引用或指针被称为向上强制转换(upcasting),这使公有继承不需要进
行显式类型转换。该规则是is-a关系的一部分。BrassPlus 对象都是Brass对象,因为它继承了Brass对象
所有的数据成员和成员函数。所以,可以对Brass对象执行的任何操作,都适用于BrassPlus对象。因此,
为处理Brass引用而设计的函数可以对BrassPlus对象执行同样的操作,而不必担心会导致任何问题。将指
向对象的指针作为函数参数时,也是如此。向上强制转换是可传递的,也就是说,如果从BrassPlus 派生出
BrassPlusPlus 类,则Brass指针或引用可以引用Brass 对象、BrassPlus对象或BrassPlusPlus对象。
相反的过程 -- 将基类指针或引用转换为派生类指针或引用 -… 称为向下强制转换(downcasting)。
如果不使用显式类型转换,则向下强制转换是不允许的。原因是is-a关系通常是不可逆的。派生类可以新
增数据成员,因此使用这些数据成员的类成员函数不能应用于基类。例如,假设从Employee类派生出Singer
类,并添加了表示歌手音域的数据成员和用于报告音域的值的成员函数range(),则将range()方法应用于
Employee 对象是没有意义的。但如果允许隐式向下强制转换,则可能无意间将指向Singer的指针设置为一
个Employee对象的地址,并使用该指针来调用range()方法(参见图13.4)。
dlals Frpiomn
priratag
Epleyte vens:
Singer trilar
Banger . pa (sigger PRrbtg;
允许向上隐式类型转换
必须向下显式类型转换
向上转换带来安全操作,因为
Singor №Employee
(每个singer都维承姓名)
向下转换可能带来不安全的操作,
因为Paployeo并不是Singer
(Eaployeefirange(方法)。
图13.4 向上强制转换和向下强制转换