C++:多态原理剖析

定义一个类:

class Animal
{
public:

    void speak()
    {
        cout << "动物在说话" << endl;
    }
};

类内只有一个非静态的成员函数,这个函数并不属于类的对象(分开存储),相当于一个空类。此时打印类的占用空间大小,发现占用内存为1.(即空类大小为1)

void test02()
{
    cout << sizeof(Animal) << endl;//结果为1
}

接下来在这个成员函数前加上virtual关键字,再次打印类占用内存大小,发现结果为4.

class Animal
{
public:

    virtual void speak()
    {
        cout << "动物在说话" << endl;
    }
};
void test02()
{
    cout << sizeof(Animal) << endl;//结果为4
}

这是为什么呢?接下来先介绍一个东西:vfptr
v即virtual
f即function
ptr即pointer
合起来即virtual function pointer,即虚函数指针
这个指针会指向一个虚函数表
在之前的Animal类中我们定义了虚函数:

virtual void speak()
    {
        cout << "动物在说话" << endl;
    }

虚函数会有一个地址,取地址:&Animal::speak (即Animal类中的speak函数的地址)
这个地址会放在vftable中,即虚函数表中。
指针vfptr指向这个虚函数表:
在这里插入图片描述
我们定义了cat类,并继承了Animal类,此时cat类中的虚函数表中继承了animal类中的一切:
在这里插入图片描述

然后在cat子类中,我们重写了Animal父类的虚函数:

void speak()
    {
        cout << "小猫说话喵喵喵" << endl;
    }

当子类重写父类的虚函数,子类中的虚函数表内部会将继承的父类虚函数表替换成(即覆盖)子类的虚函数地址(父类中的表不变化,只是子类把自己继承的给换了):
在这里插入图片描述
在这里插入图片描述

当父类的指针或引用指向子类对象时候,就发生了多态。

doSpeak函数中调用的是animal类(父类)中的speak函数:

void doSpeak(Animal& animal)//Animal &animal = cat
{
    animal.speak();
}

当你创建cat对象,并把cat对象传给这个父类speak函数:

Cat cat;
doSpeak(cat);

此时指针指的是cat对象:Animal &animal = cat
那么函数调用时就从cat的虚函数表中找这个speak函数,调用cat自己的speak函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值