返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++动态联编介绍
  • 491
分享到

C++动态联编介绍

2024-04-02 19:04:59 491人浏览 独家记忆
摘要

目录一、静态联编和动态联编1.指针和引用类型的兼容性2.虚函数的工作原理文章转自:公众号:Coder梁(ID:Coder_LT) 一、静态联编和动态联编 当我们使用程序调用函数的时候

文章转自:公众号: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++动态联编内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++动态联编介绍

本文链接: https://lsjlt.com/news/161622.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C++动态联编介绍
    目录一、静态联编和动态联编1.指针和引用类型的兼容性2.虚函数的工作原理文章转自:公众号:Coder梁(ID:Coder_LT) 一、静态联编和动态联编 当我们使用程序调用函数的时候...
    99+
    2024-04-02
  • C#条件编译、内联函数、CLS介绍
    1、条件编译 #if 条件编译会隐藏非条件(#else if)代码,我们开发中很可能会忽略掉这部分代码,当我们切换条件常量到这部分代码时,很可能因为各种原因导致报错。 如果...
    99+
    2024-04-02
  • C语言动态内存管理介绍
    目录前言:C 语言为内存的分配和管理提供了几个函数:1.malloc() 用法2.calloc() 用法3.realloc() 与 free() 用法前言: 简单记录一下,内存管理...
    99+
    2024-04-02
  • 关于C语言动态内存管理介绍
    目录1.为什么需要动态内存分配2.有关动态内存函数介绍2.1 malloc和free2.2 calloc函数2.3 realloc函数3. 常见的动态内存错误3.1 对NULL指针进...
    99+
    2024-04-02
  • C#泛型编程介绍
    例子代码: 复制代码 代码如下:class Program    {       ...
    99+
    2022-11-15
    C#泛型
  • C++静态持续变量介绍
    目录1、auto关键字2、静态持续变量1、auto关键字 我们现在知道,使用auto关键字可以自动推导变量类型,尤其是在一些很复杂的情况下,使用auto可以大大简化代码。但是在早期的...
    99+
    2024-04-02
  • Springboot中动态语言groovy介绍
    目录GroovypomResourceScriptSourceDatabaseScriptSourceGroovy Groovy是一种基于Java的语法的基于JVM的编程语言。Gro...
    99+
    2024-04-02
  • JavaAOP动态代理详细介绍
    目录1.IOC与AOP概念2.为何使用动态代理2.1 JDK原生动态代理2.1.1 MathService接口类2.1.2 MathServiceImpl实现接口类2.1.3 Pro...
    99+
    2024-04-02
  • Java动态代理简单介绍
    目录1.代理模式2.静态代理实现3.动态代理实现1.代理模式 当我们需要调用某个类(具体实现类)的方法时,不直接创建该类的对象,而是拿到该类的代理类对象,通过代理对象,调用具体实现类...
    99+
    2024-04-02
  • C#中内联函数的用法介绍
    C++ 中有个内联函数,使用 inline 来修饰函数,编译器就会对其进行优化,将此函数作为代码判断插入到调用处。 函数调用在执行时,首先要在栈中为形参和局部变量分配存储空间,然后还...
    99+
    2024-04-02
  • C++movesemantic移动语义介绍
    目录前言移动构造为什么我们需要move semantic前言 在说移动语义之前 本文作者假设你已经具备了深拷贝浅拷贝左值右值等基本概念 本文不会再过多叙述 那么接下来 让我们开始吧 ...
    99+
    2024-04-02
  • C# 最基础知识介绍--多态
    目录一、C# 多态性二、静态多态性三、函数重载四、C# 运算符重载1、运算符重载的实现 2、可重载和不可重载运算符五、动态多态性前言:👻🎄 学过编程...
    99+
    2024-04-02
  • C++实操之内联成员函数介绍
    目录前言什么是内联函数:如何使一个函数成为内联:为什么使用内联:优点 :缺点 :关键点 :总结前言 在C语言中,我们使用了宏函数,这是编译器用来减少执行时间的一种优化技术。那么问题来...
    99+
    2024-04-02
  • C#图形编程GDI+基础介绍
    编写图形程序时需要使用GDI(Graphics Device Interface,图形设备接口),从程序设计的角度看,GDI包括两部分:一部分是GDI对象,另一部...
    99+
    2024-04-02
  • C++编程语言中stringstream类介绍
    stringstream是C++标准库中的一个类,用于处理字符串的输入输出。它是基于内存缓冲区的输入输出流,可以将字符串转换为各种类...
    99+
    2023-09-09
    C++
  • Java并发编程之线程状态介绍
    目录线程状态概述睡眠sleep方法等待和唤醒等待唤醒的一个小例子线程状态概述 线程由生到死的完整过程: 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态...
    99+
    2024-04-02
  • C/C++中多态性详解及其作用介绍
    目录概述静态多态函数重载运算符重载动态多态非动态动态概述 多态性 (polymorphism) 是面向对象程序设计的一个重要特征. 利用多态性扩展设计和实现一个易于扩展的系统. C...
    99+
    2024-04-02
  • C++关于指针,继承和多态介绍
    目录指针指针和继承指针、继承和多态指针 我们在书本上学到的指针基本上都是:首先,指针是一个变量;其次,这个变量存储的值是一个地址。这个是对指针的一个基本理解,最近在编程中发现了一些新...
    99+
    2024-04-02
  • C++ opencv将图片动漫化介绍
    目录边缘检测贴边缘图到原图双边滤波HSI空间修改饱和度后续:总结最近对图像处理十分感兴趣,也学着用opencv 实现各种简单的图像处理,因此,有了下面的实验,就是将照片处理成漫画的风...
    99+
    2024-04-02
  • C#并行编程Task类用法介绍
    Task和ThreadPool的功能类似,可以用来创建一些轻量级的并行任务。对于将一个任务放进线程池 ThreadPool.QueueUserWorkItem(A); 这段代码用Ta...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作