1、什么是虚函数
带有virtual关键字修饰的函数就是虚函数。
class Test
{
public:
void fun1();//普通函数
virtual void func2();//虚函数
};
2、为什么要使用虚函数
引入虚函数,是为了使用多态的特性(通过父类指针调用子类重写的方法)。
案例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.
结论:只有将父类函数声明为虚函数,才可以通过父类指针调用子类中重写的方法,也就实现了多态的特性。
3、纯虚函数
纯虚函数是在虚函数声明的末尾加上=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.