在 C++ 中多态是如何实现的

在 C++ 中,多态的实现是在基类的函数前加上 virtual 关键字使其成为虚函数,并在派生类中重写该函数;该函数运行时会根据引用或指针绑定的对象的真实类型来决定要执行的版本。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。

1. 多态性

多态性是面向对象程序设计(OOP)的核心思想,其字面意思是多种形态。

当我们使用基类的引用或者指针调用基类中定义的一个函数时,我们并不知道该函数真正作用的对象是什么类型,它可能是一个基类的对象也可能是一个派生类的对象。如果该函数是虚函数,则直到运行时才会决定到底执行哪个版本,判断的依据是引用或指针绑定的对象的真实类型。

另一方面,对非虚函数的调用和通过对象进行的函数(虚函数或非虚函数)调用在编译时进行绑定。

2. 虚函数

对于某些函数,基类希望它的派生类各自定义适合自身的版本,此时基类就将这些函数声明成虚函数。

基类通过在其成员函数的声明语句之前加上关键字 virtual 使得该函数执行动态绑定。关键字 virtual 只能出现在类内部的声明语句之前而不能用于类外部的函数定义。

任何构造函数之外的非静态函数都可以是虚函数。

如果基类把一个函数声明成虚函数,则该函数在派生类中隐式地也是虚函数。当然,我们可以再一次使用 virtual 关键字指出该函数的性质。

在 C++11 中我们可以使用 override 关键字来说明派生类中的虚函数。如果我们使用 override 标记了某个函数,但该函数并没有覆盖已存在的虚函数,此时编译器将报错。

通常情况下,如果我们不使用某个函数,则无须为该函数提供定义。但是我们必须为每一个虚函数都提供定义,而不管它是否被用到了,这是因为连编译器也无法确定到底会使用哪个虚函数。

3. 纯虚函数

我们通过在函数体的位置(即在声明语句的分号之前)书写 =0 就可以将一个虚函数说明为纯虚函数。其中,=0 只能出现在类内部的虚函数声明语句处。

和普通的虚函数不一样,一个纯虚函数无需定义。我们可以将纯虚函数的函数体定义在类的外部,但不能在类的内部为一个 =0 的函数提供函数体。

含有(或者未经覆盖直接继承)纯虚函数的类是抽象基类。抽象基类负责定义接口,而后续的其他类可以覆盖该接口。我们不能(直接)创建一个抽象基类的对象。

4. 虚表

编译器会为每个包含虚函数的类创建一个虚函数表(或称虚表),该表是一个一维数组,在这个数组中存放每个虚函数的入口地址。编译器会在每个对象的前四个字节中保存一个虚表指针(即 vptr,一般作为类对象的第一个成员),指向对象所属类的虚表。

虚表和类是对应的,虚表指针和对象是对应的。在构造函数中进行虚表的创建和虚表指针的初始化。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值