(一)、虚函数
1.什么是虚函数:
虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数
2.虚函数的格式:
class Student { virtual void show(){} } class Student1 :public Student { void show(){} }
3.关于虚函数的注意事项:
1、 必须把动态联编的行为定义为类的虚函数。
2、类之间存在父子类型关系,一般表现为一个类从另一个类公有派生而来。
3、 必须先使用基类指针或者引用指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。
4.虚函数的作用:
可以让成员函数操作一般化,用基类的指针指向不同的派生类的对象时,基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数,
而不是基类中定义的成员函数(只要派生类改写了该成员函数)。
若不是虚函数,则不管基类指针指向的哪个派生类对象,调用时都
会调用基类中定义的那个函数。
5.虚函数访问格式
指针变量->成员函数
6.虚函数的各种疑难杂症
【当指针是基类、但虚函数不在基类时】
代码展示:
#include <iostream> using namespace std; class A { public: void fun() { cout << "调用了A" << endl; } }; class B:public A { public: void fun() { cout << "调用了B" << endl; } }; class C:public A { public: virtual void fun() { cout << "调用了C" << endl; } }; int main() { A a,*p; B b; C c; p = &c; p->fun(); }
效果展示:
【当指针在派生类,虚函数在基类,指向派生类】
代码展示:
#include <iostream> using namespace std; class A { public: virtual void fun() { cout << "调用了A" << endl; } }; class B:public A { public: void fun() { cout << "调用了B" << endl; } }; class C:public A { public: void fun() { cout << "调用了C" << endl; } }; int main() { A a; B b; C c,*p; p = &c; p->fun(); }
效果展示:
1.【基类和派生类都为虚函数,指针在基类指向派生类】
父类的与子类的同名虚函数,在继承的时候,子类会将父类的覆盖,
代码展示:
#include <iostream> using namespace std; class A { public: virtual void fun() { cout << "调用了A" << endl; } }; class B:public A { public: void fun() { cout << "调用了B" << endl; } }; class C:public A { public: virtual void fun() { cout << "调用了C" << endl; } }; int main() { A a,*p; B b; C c; p = &c; p->fun(); }
效果展示:
2.【基类和派生类都有虚函数,指针在基类指向基类】
代码展示:
#include <iostream> using namespace std; class A { public: virtual void fun() { cout << "调用了A" << endl; } }; class B :public A { public: void fun() { cout << "调用了B" << endl; } }; class C :public A { public: virtual void fun() { cout << "调用了C" << endl; } }; int main() { A a, * p; B b; C c; p = &a; p->fun(); }
效果展示:
3.【基类和派生类都有虚函数,指针在派生类指向派生类】
代码展示:
#include <iostream> using namespace std; class A { public: virtual void fun() { cout << "调用了A" << endl; } }; class B:public A { public: void fun() { cout << "调用了B" << endl; } }; class C:public A { public: virtual void fun() { cout << "调用了C" << endl; } }; int main() { A a; B b; C c,*p; p = &c; p->fun(); }
效果展示:
4.【基类和派生类都有虚函数,指针在派生类指向基类】
错误分析:派生类访问不到基类
代码展示:
#include <iostream> using namespace std; class A { public: virtual void fun() { cout << "调用了A" << endl; } }; class B :public A { public: void fun() { cout << "调用了B" << endl; } }; class C :public A { public: virtual void fun() { cout << "调用了C" << endl; } }; int main() { A a; B b; C c,*p; p = &a; p->fun(); }
效果展示:
7.虚函数的示范
【非虚函数的调用,会适当其反】
代码展示:
#include <iostream> using namespace std; class A { private: int number; public: A(int nu=21032114) :number(nu) {} void show() { cout << "基类,学号为:" << number<<endl; } }; class B:public A { private: int score; public: B(int sc = 86) :score(sc) {} void show() { cout << "派生,成绩为:" << score<<endl; } }; int main() { A a; a.show(); B b; b.show(); A* p; p = &b; p->show(); //我想调用派生类,但仍然是基类的函数 A& p1 = b; b.show(); return 0; }
效果展示: