虚函数的作用
虚函数的作用:实现多态
相关类的解释
类名公共行为(吃)的具体表现动物类吃东西狗类吃屎人类吃饭
横向对比发现
动物类:吃的动作很模糊:没有具体讲吃什么:所以动作内容是:吃东西 狗类:吃的动作很具体:狗的特性是吃屎:所以动作内容是:吃屎人类:吃的动作很具体:人的特性是吃饭:所以动作内容是:吃饭
纵向对比
动物类:是一个大类(父亲) 狗类:是动物类的某一个个类(子类)人类:是动物类的某一个(子类)
程序解释
定义的类有 : 动物类(父类) 狗类(子类) 人类(子类)
类中实现的函数有 :纯虚函数 虚函数 正常函数 注:函数代表吃的动作
父类指针开辟子类对象: 其中的 m_Dog 以及 m_People 都是Animal的指针 Dog People 子 类对象
Animal *m_Dog = new Dog();
Animal *m_People = new People();
类代码
//<<动物类
class Animal
{
public:
//<<纯虚函数
virtual void f_virtual_pure_EatFood() = 0;
//<<虚函数
virtual void f_virtual_EatFood()
{
qDebug()<<"虚函数:动物吃东西";
}
//<<虚函数:此虚函数子类不实现
virtual void f_virtual_EatFood_NoFinish()
{
qDebug()<<"虚函数:动物吃东西:子类不实现";
}
//<<正常函数
void EatFood()
{
qDebug()<<"正常函数:动物吃东西";
}
};
//<<狗类
class Dog:public Animal
{
public:
//<<纯虚函数
void f_virtual_pure_EatFood() override
{
qDebug()<<"纯虚函数:狗吃屎";
}
//<<虚函数
virtual void f_virtual_EatFood() override
{
qDebug()<<"虚函数:狗吃屎";
}
//<<正常函数
void Dog_EatFood()
{
qDebug()<<"正常函数:狗吃屎";
}
};
//<<狗类
class People:public Animal
{
public:
//<<纯虚函数
void f_virtual_pure_EatFood() override
{
qDebug()<<"纯虚函数:人吃饭";
}
//<<虚函数
virtual void f_virtual_EatFood() override
{
qDebug()<<"虚函数:人吃饭";
}
//<<正常函数
void Dog_EatFood()
{
qDebug()<<"正常函数:人吃饭";
}
};
函数输出
狗类
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Animal *m_Dog = new Dog();
m_Dog->EatFood(); //<<正常函数:动物吃东西
m_Dog->f_virtual_EatFood(); //<<虚函数:狗吃屎
m_Dog->f_virtual_pure_EatFood(); //<< 纯虚函数:狗吃屎
m_Dog->f_virtual_EatFood_NoFinish();//虚函数:动物吃东西:子类不实现
return a.exec();
}
结论
正常函数:父类的动作(吃东西)
虚函数:子类实现的动作(狗吃屎)
纯虚函数:子类实现的动作(狗吃屎)
纯虚函数子类不实现:父类动作(吃东西)
我们可以发现,在狗类中,虚函数与纯虚函数,都被重写了(狗类中实现),这相当于把父类(动物 类)中的,吃东西,这个动作,给具体化了。由 父类(动物类):吃东西 ------->子类(狗类):狗吃屎。 但是在, 纯虚函数子类不实现,这个函数中,我们并没有,重写虚函数,这就导致了,并没有具体化吃东西。所以是父类的动作(吃东西)。
人类
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Animal *m_People = new People();
m_People->EatFood(); //<<正常函数:吃东西
m_People->f_virtual_EatFood(); //<<虚函数:人吃饭
m_People->f_virtual_pure_EatFood(); //<< 纯虚函数:人吃饭
m_People->f_virtual_EatFood_NoFinish();//<<虚函数:动物吃:子类不实现
return a.exec();
}
结论
正常函数 :父类实现动作(吃东西)
虚函数:子类实现动作(人吃饭)
纯函数:子类实现动作(人吃饭)
虚函数子类不实现:父类动作(吃东西)
我们可以发现,在人类中,虚函数与纯虚函数,都被重写了(人类中实现),这相当于把父类(动物 类)中的,吃东西,这个动作,给具体化了。由 父类(动物类):吃东西 ------->子类(人类):人吃饭。 但是在, 纯虚函数子类不实现,这个函数中,我们并没有,重写虚函数,这就导致了,并没有具体化吃东西。所以是父类的动作(吃东西)。
最终结论
父类指针:Animal *m_People ; Animal *m_Dog
开辟: new
子类对象 :People(); Dog();
这是一种多态行为,不通的子类对象,有不同的行为方式。(人吃饭) (狗吃屎)
接口统一(虚函数名字一样),实现不同(不同的子类,有不同的方法)
注意事项
虚函数与纯虚函数的不同点:
虚函数:需要再父类中实现,子类中不一定要实现
纯虚函数:在父类中不实现,一定要在子类中实现, 如果子类不实现(报错)