多态实现--虚函数与纯虚函数

Posted 技术不支持

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多态实现--虚函数与纯虚函数相关的知识,希望对你有一定的参考价值。

多态实现--虚函数与纯虚函数

  • C++中实现多态是使用虚函数表的方法实现的。
  • 那么具体怎么实现的呢?

举例说明

  • 假设有这样一个多态场景:
  • 有一个基类动物(animal类),动物里面又有两个派生类:猫(cat类)和狗(dog类)。现在要求动物类有一个共同的方法:叫声(voice成员函数),但猫和狗叫声是不同的(即:它们的叫声实现方法不同)。
  • 那么代码怎么写呢?

多态的代码实现

#include <iostream>
using namespace std;

//1、 定义一个纯虚函数
class animal
{
public:
    virtual void voice()= 0;    //纯虚函数voice
};

//2、 定义猫(cat)狗(dog)类,共同继承自animal,但对voice进行了具体实现
class cat:public animal
{
public:
    virtual void voice()
    {
        cout <<"喵喵喵"<<endl;
    }
};

class dog:public animal
{
public:
    virtual void voice()
    {
        cout <<"汪汪汪"<<endl;
    }
};

//3、那么下一步就要给猫和狗做一个统一接口了,传参用基类指针。这个接口只有一个功能,就是调用动物叫声voice。
void animal_voice(animal * a)
{
    a->voice();
}

//4、 多态写好了,我们来调用一下试试,写个test看看这个多态有没有问题。我们分别定义一个猫狗对象,来调用统一接口,看看它们的叫声是否相同。

void test()
{
    cat c;
    dog d;
    animal_voice(&c);
    animal_voice(&d);
}

int main()
{
    test();
    return 0;
}
  • 验证结果:

    喵喵喵
    汪汪汪

说明这个多态已实现完成。

多态原理

  • 那么多态的原理是怎么样的呢?为什么这样写代码,就能实现猫和狗叫声不同,它们明明调用的是同一个接口呀?

  • 我们知道C++在编译时为我们做了很多背后的工作。它为cat和dog分别生成了一张虚函数表,将函数地址(也就是函数指针)记录在各自的虚函数表中。如图所示。

    • cat的虚函数表:
cat的虚函数表
cat的voice函数的地址
- dog的虚函数表:
dog的虚函数表
dog的voice函数的地址
  • 这样当我们用接口调用cat和dog的voice函数时,它们会各自在自己的虚函数表里找到自己的voice函数地址,然后根据这个地址来进行调用了。怎么样,多态实现很简单吧?

虚函数与纯虚函数

  • 那么animal里的纯虚函数virtual void voice()= 0;只能这样写吗?它可以像下面这样写成虚函数吗?
    ```
    virtual void voice()
    {

}
```

  • 答案是可以,但它们是不同的。这里的虚函数是有实现的,只是它的实现方法是空,那么在cat和dog中我们再次实现这个voice就相当于重写(也就是说,我们也可以选择省略(即:不重写)这个voice)。但如果写成纯虚函数,那么我们就必须要在cat和dog中具体实现voice。

  • 也就是这里的虚函数是有这个函数的实现,只是为空;而纯虚函数是这个函数根本还没实现。

以上是关于多态实现--虚函数与纯虚函数的主要内容,如果未能解决你的问题,请参考以下文章

虚函数与纯虚函数

C++ 运行时多态

C ++:私有虚函数与纯虚函数[重复]

关于虚函数与纯虚函数的区别

虚函数与纯虚函数--定义问题

虚析构函数与纯虚函数