定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。
定义一个函数为纯虚函数,才代表函数没有被实现。
定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被成为“虚”函数。
虚函数只能借助于指针或者引用来达到多态的效果。
通过代码实例来具体学习下:
目标是有三个动物子类Cat,Dog,Mouse。每个动物子类都有做次自我介绍,目的是只让Cat类做自我介绍,就是要检测Cat子类。
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;
class Cat;
class Dog;
class Mouse;
class Animal
{
public:
class IVisitor //通过一个接口来汇报自己是谁
{
public:
virtual ~IVisitor() //析构函数也要为虚函数
{
}
virtual void Visit(Cat* animal) = 0; //纯虚函数,子类若想实例化必须override
virtual void Visit(Dog* animal) = 0;
virtual void Visit(Mouse* animal) = 0;
};
private:
string name;
public:
Animal(const string& theName)
:name{theName}
{
}
virtual ~Animal()
{
}
const string& GetName()const
{
return name;
}
virtual string Introduce()const = 0;
virtual void Accept(IVisitor* visitor) = 0; //接受函数
};
class Cat : public Animal
{
public:
Cat(const string& theName)
:Animal{theName}
{
}
string Introduce()const override
{
return "我是一只猫,我的名字叫\"" + GetName() + "\"。";
}
void Accept(IVisitor* visitor)override
{
visitor->Visit(this); //执行类里的函数
}
};
class Dog : public Animal
{
public:
Dog(const string& theName)
:Animal{theName}
{
}
string Introduce()const override
{
return "我是一只狗,我的名字叫\"" + GetName() + "\"。";
}
void Accept(IVisitor* visitor)override
{
visitor->Visit(this);
}
};
class Mouse : public Animal
{
public:
Mouse(const string& theName)
:Animal{theName}
{
}
string Introduce()const override
{
return "我是一只老鼠,我的名字叫\"" + GetName() + "\"。";
}
void Accept(IVisitor* visitor)override
{
visitor->Visit(this);
}
};
class OnlyPrintCatVisitor : public Animal:: IVisitor
{
public :
void Visit(Cat* animal)override
{
cout << animal->Introduce() << endl;
}
void Visit(Dog* animal)override
{}
void Visit(Mouse* animal)override
{}
};
int main()
{
auto tom = make_shared<Cat>("Tom");
auto jerry = make_shared<Mouse>("Jerry");
auto spike = make_shared<Dog>("Spike");
auto butch = make_shared<Cat>("Butch");
auto lightning = make_shared<Cat>("Lightning");
vector<shared_ptr<Animal>> friends{ tom, jerry, spike, butch, lightning };
OnlyPrintCatVisitor visitor;
for (auto animal : friends)
{
animal->Accept(&visitor);
}
return 0;
}