动手写9.2.1
动手写9.2.1展示了虚函数的应用。运行结果如图9.2.1所示:
图9.2.1 虚函数的应用
在本示例的main()函数中,我们定义了一个指向基类的指针,并把新分配内存的派生类的地址赋值给它。由于我们在基类中给move()函数加了virtual(虚拟的)关键字,我们可以直接使用基类指针调用派生类中实现的虚函数版本,在运行结果中打印出来的不是“交通工具行驶”,而是“飞机飞行”和“汽车行驶”。有了这一特性以后,我们可以在程序运行的时候根据用户的输入给基类指针绑定不同的派生类,以产生不同的行为,这也叫作动态绑定(Dynamic Binding)。
此外,virtual关键字在派生类中可以省略,编译器会自动将相同函数签名的派生类成员函数也识别为虚函数,但为了可读性还是加上它比较好。然而,基类中的virtual关键字却是必要的,如果遗漏了,就不能达到上述示例的效果了。
动手写9.2.2(www.xing528.com)
动手写9.2.2展示了基类中没有用virtual关键字的情况。运行结果如图9.2.2所示:
图9.2.2 没有virtual关键字的情况
如果基类没有用virtual关键字,在调用move()的时候就只会调用基类的move()。这是为什么呢?实际上虚函数的位置与普通函数不同,虚函数位于类的开头,所以在类型转换的时候不存在被截取的问题。派生类的虚函数版本在其中会覆盖基类的虚函数版本,而派生类的普通成员函数位于派生类额外的一块内存中,在赋值地址给基类的指针时,派生类转换成了基类,所以基类指针看不见派生类的move(),而只会调用自己的move()。
除了virtual关键字之外,使用虚函数也需要基类的指针或引用,而不是基类本身。我们来看一看不用指针的情况:
动手写9.2.3
动手写9.2.3展示了不用指针调用虚函数的情况,运行结果与动手写9.2.2的相同,都是只调用了基类的move()。这是因为在转换派生类为Vehicle并赋值或初始化vehicle的过程中,派生类的虚函数并不会跟着复制过来,因此Vehicle只能调用自己的版本。这其中涉及虚函数的实现原理,但是我们只要记住基类本身不能调用派生类的虚函数这一规则就行了。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。