C++动态联编介绍

 更新时间:2022年01月05日 10:20:27   作者:梁唐  
这篇文章主要介绍了C++动态联编,在C++中,联编是指一个计算机程序的不同部分彼此关联的过程。按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编和动态联编

文章转自:公众号:Coder梁(ID:Coder_LT)

一、静态联编和动态联编

当我们使用程序调用函数的时候,究竟应该执行哪一个代码块呢?将源代码中的函数调用解释为执行特定的函数代码块这个过程被称为函数名联编(binding)。

在C语言当中,这非常简单,因为每个函数名都对应一个不同的函数。而在C++当中,由于支持了函数重载,使得这个任务变得更加复杂。编译器必须要查看函数的参数以及函数名才能确定。好在函数的选择以及参数在编译的时候都是确定的,所以这部分联编在编译时就能完成,这种联编被称为静态联编。

在有了虚函数之后, 这个工作变得更加复杂。因为使用哪一个函数不能在编译时确定了,因为编译器不知道用户将选择哪个类型的对象。所以,编译器必须能在程序运行的时候选择正确的虚函数,这被称为动态联编。

1.指针和引用类型的兼容性

在C++当中,动态联编与指针和引用调用方法相关,这是由继承控制的。前文当中说过,公有继承建立的is-a关系,使得我们可以用父类指针或引用指向子类的对象。而在C++当中,是不允许将一种类型的地址赋值给另外一种类型的指针的。

下面两种操作都是非法的:

double x = 2.5;
int *pi = &x; // 非法
long &r = x; // 非法

将派生类引用或指针转换成基类的引用和指针称为向上强制转换(upcasting),这种规则是is-a关系的一部分。因为派生类继承了基类当中所有的数据成员和成员函数,因此基类成员能够进行的操作都适用于子类成员,所以向上强制转换是可传递的。

如果反过来呢?将父类对象传递给子类指针呢?这种操作被称为向下强制转换(downcasting),在不使用强制转换的前提下是不允许的。因为is-a关系通常是不可逆的,派生类当中往往新增了一些数据成员或方法,不能保证在父类对象上一样还能兼容。

2.虚函数的工作原理

我们在使用虚函数的时候其实可以不需要知道当中的实现原理,但是了解了工作原理能够帮助我们更好地理解理念。另外在C++相关的开发面试当中经常会问起类似的实现细节。

通常,编译器处理虚函数的方法是:给每一个对象添加一个隐藏成员,这个成员当中保存了一个指向函数地址数组的指针,这种数组称为虚函数表。

这个虚函数表中存储了当前这个类对象的声明的虚函数的地址,我们来看一个例子:

class Human {
    private:
    ...
     char name[40];
    public:
     virtual void show_name();
     virtual void show_all();
     ...
};

class Hero : public Human{
    private:
     ...
        char power[20];
    public:
     void show_all();
        virtual void show_power();
     ...
};

对于Human类型的对象,它当中除了类中声明的内容之外,还会额外多一个指针,指向一个列表,比如是[1024,1222]。

这里的1024和1222分别是show_nameshow_all两个函数代码块的地址。

同样Hero子类当中也会有这样一个指针指向一个虚函数的列表,由于我们在Hero子类当中没有重载show_name方法,所以Hero类型的对象中的列表中的第一个元素仍然是1024。由于我们重载了show_all方法,以及我们新增了一个show_power的虚函数,因此它的虚函数列表可能是[1024,2333,3777]

简单来说,当我们调用虚函数的时候, 编译器会先通过每个对象中的虚函数列表指针拿到虚函数列表。然后在找到对应位置的虚函数代码块的地址,最后进行执行。

显然这个过程涉及到维护虚函数地址表,以及函数执行时有额外的查表操作,既带来了存储空间的消耗,也带来了性能的消耗。

到此这篇关于C++动态联编介绍的文章就介绍到这了,更多相关C++动态联编内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++设计模式编程中proxy代理模式的使用实例

    C++设计模式编程中proxy代理模式的使用实例

    这篇文章主要介绍了C++设计模式编程中proxy代理模式的使用实例解析,代理模式可以被归类为结构型的设计模式,代理模式主张为对象提供一种代理以控制对这个对象的访问,需要的朋友可以参考下
    2016-03-03
  • C语言之快速排序案例详解

    C语言之快速排序案例详解

    这篇文章主要介绍了C语言之快速排序案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++实现俄罗斯方块

    C++实现俄罗斯方块

    这篇文章主要为大家详细介绍了C++实现俄罗斯方块,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • Windows上使用vs编译fdk-aac的教程详解

    Windows上使用vs编译fdk-aac的教程详解

    有时需要在Windows上用到fdk-aac,fdk-aac是源码是cmake的,可以直接转成vs项目,下面就跟随小编一起学习一下如何在Windows上使用vs编译fdk-aac吧
    2023-11-11
  • C++ std::shared_mutex读写锁的使用

    C++ std::shared_mutex读写锁的使用

    本文主要介绍了C++ std::shared_mutex读写锁的使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++设计模式之外观模式(Facade)

    C++设计模式之外观模式(Facade)

    这篇文章主要为大家详细介绍了C++设计模式之外观模式(Facade),具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • Visual Studio Code 2020安装教程及CPP环境配置(教程图解)

    Visual Studio Code 2020安装教程及CPP环境配置(教程图解)

    这篇文章主要介绍了Visual Studio Code 2020安装教程、CPP环境配置,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • 使用C语言判断栈的方向实例

    使用C语言判断栈的方向实例

    下面小编就为大家带来一篇使用C语言判断栈的方向实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,祝大家游戏愉快哦
    2016-12-12
  • 深入单链表的快速排序详解

    深入单链表的快速排序详解

    本篇文章是对单链表的快速排序进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C语言分支循环其嵌套语句的使用

    C语言分支循环其嵌套语句的使用

    本文主要介绍了switch 嵌套和循环嵌套,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11

最新评论