前面一节课中讲到了函数重写,最后也提出了一个问题,怎么解决函数重写和赋值兼容之间的问题?
首先回顾下,父类中被重写的函数依然会继承给子类,只是子类中的重写函数会覆盖父类的 被重写函数。但是当函数重写和赋值兼容遇上了后编译器为了安全着想只会调用父类中的函数,这显然不符合我们的期望。而面向对象中期望的行为是:
根据实际的对象类型来判断如何调用重写函数。
父类指针(引用)指向(替代)父类对象则调用父类对象中定义的函数。
父类指针(引用)指向(替代)子类对象则调用子类对象中定义的函数。
面向对象中的多态的概念;
根据实际对象的类型来决定调用函数的具体目标。
同样的语句在实际运行时有不同的表现形态。
幸运的是,C++直接支持多态的概念,通过virtual关键字来支持多态的行为,也是C++中唯一支持多态的方式,被virtual声明的函数叫做虚函数,拥有多态的特性。所以上一节的实例中我们只需在父类中将被重写的函数声明之前加上virtual关键字就可以解决问题,同时也让子类中的同名函数也变成虚函数。
多态的意义表现在于程序运行时表现出多态的特性,函数重写必须实现多态,否则没有任何意义, 多态是面向对象组件化程序设计的基础特性。
了解一下什么叫做静态联编和动态联编,静态联编就是在程序编译时就能确定调用哪个函数,比如函数重载;动态联编就是需要在程序运行时才能确定的调用函数,比如函数重写。
构造函数是否可以作为虚函数?
肯定是不能的,因为构造函数在执行完成之前不能保证正确的初始化虚函数表,而只有当构造函数结束后才能正确的初始化虚函数表指针。
析构函数是否可以作为虚函数?
是可以的,而且工程中建议在设计类时将析构函数设置为虚函数,因为虚函数作为析构函数时,能够防止析构函数被漏掉调用,防止内存泄漏。
构造函数中不可能发生多态行为,只能调用当前类中定义的函数版本。
在构造函数执行时,虚函数表未被正确初始化。
析构函数中不可能发生多态行为,只能调用当前类中定义的函数版本。
在析构函数执行时,虚函数表指针已经被销毁。