虚函数
多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数(比如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;
所以有纯虚函数的类也是不能被直接实例化的。