虚函数

看这样一个例子:
先定义一个类(人类),类里有一个成员函数:人有俩眼睛

class Human
{
private:
    /* data */
public:
    Human(/* args */);
    ~Human();
    void eyes();
};

Human::Human(/* args */)
{
}

Human::~Human()
{
}

void Human::eyes()
{
    cout<<"human have two eyes"<<endl;
}

再用这个类派生一个子类:杨戬,那很显然,杨戬有三只眼睛

class YangJian:public Human
{
private:
    /* data */
public:
    YangJian(/* args */);
    ~YangJian();
    void eyes();
};

YangJian::YangJian(/* args */)
{
}

YangJian::~YangJian()
{
}

void YangJian::eyes()
{
    cout<<"YangJian have three eyes"<<endl;
}

在主函数中分别调用这两个类的函数

int main(int argc, char const *argv[])
{
    Human xiaoming;
    xiaoming.eyes();
    YangJian yangjian;
    yangjian.eyes();
}

输出结果很美好

human have two eyes
YangJian have three eyes

人有俩眼睛,杨戬有仨。

没有任何问题。

 

现在我要在一个函数中调用这个eyes

void eyescount(Human &p)
{
    p.eyes();
}

 

接下来在主函数中分别对两个对象调用这个函数

int main(int argc, char const *argv[])
{
    Human xiaoming;
    xiaoming.eyes();
    YangJian yangjian;
    yangjian.eyes();

    eyescount(xiaoming);
    eyescount(yangjian);
}

讲道理,输出结果应该和前面一样。小明俩眼睛,杨戬仨眼睛

但是实际上的输出:

human have two eyes
YangJian have three eyes
human have two eyes
human have two eyes

问题出现了!

我传入的是YangJian这个对象的参数,但是进入函数之后调用的却是他的父类Human的函数。

 

也就是说,只有我这个函数写成这个样子,它才肯调用YangJian 的 eyes()

void eyescount(YangJian &p)
{
    p.eyes();
}

那我Human有各种子类,除了杨戬,

我还有独眼的夏侯惇,还有仨眼睛的马王爷,还有三头六臂六个眼睛的哪吒,再带上几个千手千眼的菩萨。那我这个函数得重载多少次

 

 

那么为了解决这样的问题,就有了虚函数这样一个概念。

现在回到最开始定义Human的成员函数里面

class Human
{
private:
    /* data */
public:
    Human(/* args */);
    ~Human();
    virtual void eyes();
};

我们在父类函数声明之前,加一个virtual关键字,也就是本文的虚函数

其他地方没有任何改动,再运行一遍这个程序。

human have two eyes
YangJian have three eyes
human have two eyes
YangJian have three eyes

这样打印出来的结果就回归正常了

 

有了虚函数,基类指针指向基类对象时就使用基类的成员(包括成员函数和成员变量),指向派生类对象时就使用派生类的成员。换句话说,基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现方式,我们将这种现象称为多态(Polymorphism)。

 

posted @ 2020-04-06 14:27  祁峰_1024  阅读(157)  评论(0编辑  收藏  举报