多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数(比如Son继承Parent,son.eat()就会调用Son的成员函数eat()),BUT:
class Parent { protected: void eat() { cout << ”Parent eat”; } } class Son: public Parent { protected: void eat() { cout << ”Son eat”; } } int main(){ Parent *parent; //这里是指针形式,如果是对象呢? Son son; Parent = &son; }此时调用son.eat会打印“Parent eat”,因为:
调用函数 eat() 被编译器设置为基类中的版本,这就是所谓的静态多态,或静态链接 - 函数调用在程序执行前就准备好了。有时候这也被称为早绑定,因为 eat() 函数在程序编译期间就已经设置好了。
解决办法为:
在Parent的eat()方法前增加virtual关键字。
class Parent { protected: virtual void eat(){ cout<<”Parent eat”; } }此时,调用son.eat会打印“Son eat”。
此时,编译器看的是指针parent的内容,而不是它的类型。因此,由于 Son类的对象的地址存储在 *parent 中,所以会调用Son的 eat() 函数。
对于虚函数来说,子类继承来的虚函数还是虚函数,父类和子类都有各自的函数版本,由多态方式调用的时候动态绑定。友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调用虚拟成员函数来解决友元的虚拟问题。有虚函数声明但是没有定义的类是不能直接实例化(如Parent parent)的。父类为了避免自己的虚函数被重写,可以在函数声明时增加final关键字。有纯虚函数的类为抽象类(接口)
virtual double getVolume() = 0;所以有纯虚函数的类也是不能被直接实例化的。