多态:C++虚函数与静态绑定你真的知道吗?

我创建了一个简单函数:基类:动物叫声,派生类:羊叫,均命名为speak函数。然后观察调用:

//基类

class Animal
{
public:
     void speak()
    {
        cout << "动物再说话" << endl;
    }
    
};
//派生类:

class sheep :public Animal {
public:
    void speak()
    {
        cout << "咩咩" << endl;
    }
};
//地址早绑定了 在编译阶段确定了函数地址
// 如果想让猫说话,函数地址不能提前绑定,需要在运行阶段再绑定。
void   dospeak(Animal &Animal)
{
    Animal.speak();
}
void test01()
{
    sheep s1;
    dospeak(s1);
}
int main()
{
    test01();
    system ("pause");
    return 0;
    
}

首先阅读这段代码:基类和派生类都有一个speak函数,我想调用这个Speak函数,那么它到底会生成哪个函数呢?

这段代码输出结果一定是:“动物再说话”,但是我们的本意写的代码dospeak(s1),其实是想让羊再叫。 那么我们如果给代码 基类中的speak函数 前面加一个virtural,构成虚函数呢,那么你运行就发现是:“咩咩了”!

这就是虚函数和普通函数的区别: 

你可以理解为:

你的比喻可以调整为:

  • 基类虚函数表是“壳子”:基类提供了一个“框架”(虚函数表),其中填充了默认的函数地址(如 Animal::speak)。

  • 派生类重写是“替换壳子内容”:派生类继承这个“壳子”,但用自己的函数地址替换其中的条目(如 sheep::speak)。

  • 调用时“按壳子找内容”:通过基类指针/引用调用时,实际是根据对象实际类型的“壳子”(虚函数表)找到正确的函数

  • 静态函数

  • 编译阶段确定函数地址:编译器在编译时根据指针/引用的类型(Animal&)直接绑定到 Animal::speak()

  • 派生类函数会被隐藏:即使 sheep 类定义了同名函数 speak(),它只是隐藏了基类的函数,而不是覆盖。

  • 调用结果:通过 Animal& 调用时,始终执行基类的 speak()

  • Virtual后:

  • 虚函数表(vtable):编译器会为每个类生成虚函数表,记录虚函数的实际地址。

  • 运行时动态绑定:通过基类指针/引用调用虚函数时,会根据对象的实际类型(sheep)查找虚函数表,调用正确的派生类函数。

  • 调用结果:通过 Animal& 调用时,实际执行的是 sheep::speak()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值