带有virtual关键字修饰的函数就是虚函数。
class Test { public: void fun1();//普通函数 virtual void func2();//虚函数 };引入虚函数,是为了使用多态的特性(通过父类指针调用子类重写的方法)。
案例1:没有使用虚函数
//animal.h class Animal { public: void eat();//普通函数 }; class Cat : public Animal { public: void eat(); }; //animal.cpp #include "animal.h" #include <iostream> using namespace std; void Animal::eat() { cout << "I'm eating generic food." << endl; } void Cat::eat() { cout << "I'm eating rat." << endl; } //main.cpp #include "animal.h" void func(Animal *animal) { animal->eat(); } int main(int argc, char *argv[]) { Animal *animal=new Animal; Cat *cat=new Cat; func(animal); func(cat); delete animal; delete cat; return 1; }运行结果:
I'm eating generic food. I'm eating generic food.
结论:当父类函数不是虚函数时,通过父类指针调用函数时,只会调用父类中实现的方法。
案例2:将父类函数声明为虚函数
只需要修改animal.h文件,其他文件不用修改。
//animal.h class Animal { public: virtual void eat();//虚函数 }; class Cat : public Animal { public: void eat(); };运行结果:
I'm eating generic food. I'm eating rat. 结论:只有将父类函数声明为虚函数,才可以通过父类指针调用子类中重写的方法,也就实现了多态的特性。
纯虚函数是在虚函数声明的末尾加上=0即可;
纯虚函数不能有函数体,有一个例外就是纯虚析构函数(纯虚析构函数可以有函数体);
含有纯虚函数的类为抽象类,不能被实例化,只能被子类继承;
抽象类除了有纯虚函数外,还可以有普通函数,并且普通函数必须要有函数体。
案例:
//animal.h class Animal { public: virtual void eat()=0;//纯虚函数 void run();//普通函数 }; class Cat : public Animal { public: void eat(); }; //animal.cpp #include "animal.h" #include <iostream> using namespace std; void Animal::run() { cout << "I can run." << endl; } void Cat::eat() { cout << "I'm eating." << endl; } //main.cpp #include "animal.h" void func(Animal *animal) { animal->run(); animal->eat(); } int main(int argc, char *argv[]) { Cat *cat=new Cat; func(cat); return 1; }运行结果:
I can run. I'm eating.
