C++:多态

本文围绕C++的多态和虚函数展开。介绍了多态概念,即不同对象完成同一行为结果不同。阐述虚函数定义、重写规则,多态实现前提,还区分重写、重定义和重载。讲解抽象类,分析多态实现原理,包括虚函数表。最后提及动态与静态绑定及多继承中的虚函数表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念

多态就是指在完成具体的行为时,不同的对象会产生不同的结果。就像执行一个函数时,传入两个不同的对象,产生的结果不同。

虚函数

在继承的时候,可以在继承方式前加virtual关键字来声明函数是虚拟继承。

虚函数就是在类的函数成员前加virtual关键字。

虚函数是在编译阶段实现的,一般存在于代码段。

虚函数的重写(覆盖):子类中有一个虚函数和父类中虚函数完全相同,即返回值,函数名,函数参数都相同。有一个例外,函数返回值是基类与派生类时依旧构成函数重写(协变)。

多态实现的前提

  • 调用函数的对象必须是指针或者引用。
  • 被调用的函数必须是虚函数,且完成了虚函数的重写。

重写(覆盖),重定义(隐藏),重载

重写:函数分别在基类与派生类两个不同的作用域中;两个函数都是虚函数,函数返回值,函数名;参数都相等(协变除外)。

重定义:函数分别在基类与派生类两个不同的作用域中;函数名相同;同名函数只要不构成重写就是重定义。

重载:函数在同一作用域中;但是函数名相同,参数列表必须不同。

抽象类(也叫接口类,体现接口继承)

在虚函数后面加=0(virtual void func()=0;)这个函数就叫做抽象类

包含虚函数的类叫做抽象类,抽象类不能实例化,派生类基础后也不能实例化,除非纯虚函数被重写。

可以在派生类的虚函数后家override来强制重写基类中的纯虚函数,如果没有重写,则编译报错。

多态的实现原理

如果一个函数中包含虚函数,那么它的对象就会有一个_vfptr指针存在,_vfptr指针指向虚函数表(虚表),所以_vfptr叫做虚函数表指针。

虚函数表本质是一个存虚函数指针的指针数组(vs中存在代码段),这个数组最后面放了一个nullptr。

_vfptr实在构造函数中初始化的,所以构造函数不能写为虚函数。析构函数最好写成虚函数实现多态,否则如果派生类调用基类的析构函数,就会析构错误,虽然函数名不同,但是编译器做了特殊处理。

派生类的虚表就是把基类的虚表拷贝(继承)过来,如果派生类中重写了哪个虚函数,则覆盖掉原来的虚函数。如果派生类中定义了新的虚函数,则按照声明的顺序添加到虚表中。

前提中第一点必须指针或者引用调用,因为传入对象在设置传入类型时会直接调用该传入类的虚函数,不能做到多态。

前提中第二点必须是虚函数则很好理解,如果不是虚函数,就会直接调用编译好的固定的函数。

动态绑定与静态绑定

  • 静态绑定又称为前期绑定(早绑定),在程序编译期间确定了程序的行为,也称为静态多态,比如:函数重载
  • 动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态。

多继承中的虚函数表

如果一个派生类继承自多个基类,则它会有多个虚标存在,而它自身定义的虚函数会存在与第一个基类的虚函数表中。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值