C++ 虚函数
在类的定义中,前面有virtual 关键字的成员函数就是虚函数。
1)virtual 关键字只用在类定义里的函数声明中,写函数体是不用。
2)构造函数和静态成员函数不能是虚函数。
虚函数的作用同函数重载一样,也是为了实现多态性。
以下示例中 A 和 B 定义了相同接口,分别调用时,输出不同。
class A { public: void print() { cout << "a" << endl; } }; class B: public A { public: void print() { cout << "b" << endl; } }; int main() { A a; B b; a.print(); b.print(); return 0; }
但以上并不是多态。
多态的表现形式一:
1)派生类的指针可以赋给基类指针。
2)通过基类指针调用基类和派生类中的同名虚函数时:
(1)若该指针指向一个基类的对象,那么被调用的是基类的虚函数
(2)若该指针指向一个派生类的对象,那么被调用的是派生类的虚函数。
这种机制就叫做“多态”
多态的表现形式二:
1)派生类的对象可以赋给基类引用
2)通过基类引用调用基类和派生类中的同名虚函数时:
(1)若该引用引用的是一个基类的对象,那么被调用是基类的虚函数
(2)若该引用引用的是一个派生类的对象,那么被调用的是派生类的虚函数。
这种机制也叫做“多态”
把以上代码的 main() 函数改一下:
int main() { A a; B b; A *pa = &a; A *pb = &b; pa->print(); pb->print(); return 0; }
结果如下:
问题来了,pb 明明指向的是 class B 的对象,但调用的却是 class A 的 print() 函数。
这不是我们所期望的结果,解决这个问题就需要用到虚函数。修改A、B的定义如下:
class A { public: virtual void print() { cout << "this is a" << endl; } }; class B: public A { public: virtual void print() { cout << "this is b" << endl; } };
结果如下:
当 main() 修改为引用方式时,结果同上:
int main() { A a; B b; A &ra = a; ra.print(); A &rb = b; rb.print(); return 0; }
类A的成员函数 print() 已经成了虚函数,并且类B的成员函数 print() 也成了虚函数,当基类的成员函数高为 virtual,
其派生类的同名函数也会自动变成虚函数(加不加virtual都可以)。所以类B的 print() 也成了虚函数。
总之,指向基类的指针在操作它的多态对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。
而不是根据自身类对象的类型调用相应的函数。