一、虚函数和多态
·什么是虚函数?
类的成员函数前加上virtual关键字,则这个成员函数就是虚函数。
·什么是虚函数重写?
当在子类中定义了一个与父类完全相同的(名字相同,参数相同)的虚函数时,则称子类的这个函数重写(也称覆盖)了父类的这个虚函数。
·什么是多态?
使用基类的指针或引用调用重写的虚函数时,当指向父类调用的就是父类的虚函数,指向子类调用的就是子类的虚函数。
注意:
1、虚函数与虚继承无关,只是关键字相同。虚函数是用来实现多态的,虚继承是解决菱形继承所引发的二义性和数据冗余的。
2、虚函数在子类中重写时可以不用加virtual关键字,虚函数声明和定义分离时,声明加virtual关键字,定义不加。
3、构成多态的条件:
a:虚函数重写
b:有父类的指针和引用
4、虚函数的调用原则:
b:不构成多态,跟类型有关
a:构成多态,跟对象有关
5、不要在构造函数和析构函数里面调用虚函数,因为对象是不完整的,可能发生未定义的行为。
示例:
class A
{
A()
{
virtual f();
}
~A()
{
virtual f();
}
};
class B:public A
{
B();
~B();
};
int main()
{
B b;
}
如上代码,要构造一个B类的对象b,因为B是A的子类,B要继承A所以先要构造A。又因为B的构造函数是合成的,要构造A,要去A类内调A的构造函数。但A内又调用了虚函数,A是父类,隐含一个this指针。当this指针指向f(),若f()这个虚函数重写了,则构成多态,因为此时实在构造b,对象时B类,则多态调用B的f(),但是B的f()等还没来得及定义!
同理,析构b时,先析构子类的内容,再析构父类的内容,若析构父类时调用了一个虚函数f(),则有可能构成了多态,又去掉子类的虚函数f(),但是子类已经被析构掉了!