精华内容
下载资源
问答
  • c++动态联编
    2022-04-10 13:30:29

    更多python、PHP、JAVA、C、C++教程请到友情连接: 菜鸟教程https://www.piaodoo.com

    茂名一技http://www.enechn.com

    ppt制作教程步骤 http://www.tpyjn.cn

    兴化论坛http://www.yimoge.cn

    电白论坛 http://www.fcdzs.com

    表格制作excel教程 http://www.tsgmyy.cn


    学习通 http://www.hssi.net/


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

    更多相关内容
  • 本文阐述了静态联编动态联编的概念和区别,通过具体实例分析了实现动态联编的条件,指出了虚函数是实现动态联编的基础。
  • C++静态联编动态联编 一、简介 程序调用函数时,将使用哪个可执行代码块呢?编译器负责回答这个问题。将源代码中的函数调用解释为执行特定的函数 代码块被称为函数名联编。 在C语言中,这非常简单,因为每个函数名...

    C++静态联编和动态联编

    一、简介

    程序调用函数时,将使用哪个可执行代码块呢?编译器负责回答这个问题。将源代码中的函数调用解释为执行特定的函数代码块被称为函数名联编

    在C语言中,这非常简单,因为每个函数名都对应一个不同的函数。在C++中,由于函数重载的缘故,这项任务更复杂。

    编译器必须查看函数参数及函数名才能确定使用哪个函数。然而,C/C++编译器可以在编译过程完成这种联编。

    静态联编: 在编译过程中进行联编被称为静态联编,也称为早期联编。

    动态联编: 虚函数的使用使函数名联编这项工作变的困难。使用哪一个函数是不能再编译时确定的,因为编译器不知道用户将选择哪种类型的对象。所以,编译器必须生成能够在程序运行时选择正确的虚方法的代码,这被称为动态联编,也称为晚期联编

    二、指针与引用类型的兼容性

    2.1 通常使用方式

    在C++中,动态联编与通过指针和引用调用方法相关,从某种程度上说,这是由继承控制的。公有继承建立is-a关系的一种方法是如何处理指向对象的指针和引用。通常,C++不允许将一种类型的地址赋给另一种类型的指针,也不允许一种类型的引用指向另一种类型。举例如下:

    double x = 3.2;
    int *pi = &x;		// 无效赋值,不匹配的指针类型
    long &rl = x;		// 无效赋值,不匹配引用类型
    

    2.2 继承使用方式

    指向基类的引用或指针可以引用派生类对象,而不必进行显示类型转换。举例如下:

    BrassPlus tom("Test", 1234, 1234.56);
    Brass *pb = &tom;		// 正确使用
    Brass &rb = tom;		// 正确使用
    

    2.3 继承类型转换

    向上强制转换: 将派生类引用或指针转换为基类引用或指针被称为向上强制转换,这种公有继承不需要进行显示类型转换,该规则是is-a关系的一部分。

    向下强制转换: 将基类指针引用或指针转换为派生类引用或指针,被称为向下强制转换,如果不使用显示类型转换,则向下强制转换是不允许的,原因是is-a关系通常是不可逆的。

    2.4 向上类型转换说明

    对于使用基类引用或指针作为参数的函数调用,将进行向上强制转换。举例如下:

    // 假设示例中的每个函数的代码块都调用参数的ViewAcct()函数
    void fr(Brass &rb);		// 调用rb.ViewAcct()
    void fp(Brass *pb);		// 调用pb->ViewAcct()
    void fv(Brass b);		// 调用b.ViewAcct()
    
    int main()
    {
        Brass b("Test1", 1234, 1234.56);
        BrassPlus bp("Test2", 5678, 5678.89);
        
        fr(b);				// 调用Brass::ViewAcct()
        fr(bp);				// 调用BrassPlus::ViewAcct()
        
        fp(&b);				// 调用Brass::ViewAcct()
        fp(&bp);			// 调用BrassPlus::ViewAcct()
        
        fv(b);				// 调用Brass::ViewAcct()
        fv(bp);				// 调用Brass::ViewAcct()
    }
    

    上述示例代码详解:

    • 按值传递导致只将BrassPlus对象的Brass部分传递给fv()函数。

    • 引用和指针发生的隐式向上转换导致fr()函数和fp()函数,分别为Brass对象和BrassPlus对象使用Brass::ViewAcct()和BrassPlus::ViewAcct()。

    • 隐式向上强制转换使基类指针或引用可以指向基类对象或派生类对象,因此需要动态联编。C++使用虚成员函数来满足这种需求

    三、虚成员函数和动态联编

    根据如下代码示例,回顾使用引用或指针调用方法的过程:

    Brass *b;
    BrassPlus bp;
    b = &bp;
    b->ViewAcct();
    

    如果在基类中没有将ViewAcct()函数声明为虚函数,则b->ViewAcct()将根据指针类型(Brass*)调Brass::ViewAcct()。

    指针类型在编译时已知,因此编译器在编译时,可以将ViewAcct()关联到Brass::ViewAcct()。总之,编译器对非虚方法使用静态联编

    如果在基类中将ViewAcct()函数声明为虚函数,则b->ViewAcct()根据对象类型(BrassPlus)调用BrassPlus::ViewAcct()。

    对象类型只有在运行程序时才能确定。所以编译器生成的代码将在程序执行时,根据对象类型将ViewAcct()关联到Brass::ViewAcct()或BrassPlus::ViewAcct()。总之,编译器对虚方法使用动态联编

    3.1 为什么有两种类型的联编

    如果动态联编能够让开发人员能够重新定义方法,而静态联编在这方面很差,为什么不摒弃静态联编呢?

    解:原因有两个,效率和概念模型

    效率: 为使程序能够在运行阶段进行决策,必须采取一些方法来跟踪基类指针或引用指向的对象类型,这增加了额外开销。例如,如果类不用作基类,则不需要动态联编。如果派生类不重新定义基类的任何方法,也不需要使用动态联编。

    概念模型: 在设计类时,可能包含一些不在派生类重新定义的成员函数。不将函数设置为虚函数,有两方面的好处:首先效率更高;其次,指出不要重新定义该函数。仅将那些预期将被重新定义的方法声明为虚方法。

    注: 如果要在派生类中重新定义基类的方法,则将它设置为虚方法;否则,设置为非虚方法。

    3.2 为什么默认为静态联编

    基类方法不声明为虚方法,或派生类不重新定义基类任何方法,则使用静态联编更合理,效率也更高。由于静态联编的效率更高,因此被设置为C++的默认选择。

    3.3 虚函数的工作原理

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

    虚函数表: 虚函数表中存储了为类对象进行声明的虚函数的地址。例如,基类对象包含一个指针,该指针指向基类中所有虚函数的地址表。派生类对象将包含一个指向独立地址表的指针。具体如下:

    • 如果派生类提供了虚函数的新定义,该虚函数表将保存新函数的地址;
    • 如果派生类没有重新定义虚函数,该虚函数表将保存函数原始版本的地址。
    • 如果派生类定义了新的虚函数,则该函数的地址也将被添加到虚函数表。
    • 无论类中包含的虚函数是1个或者多个,都只需要在类对象添加1个地址成员,只是表的大小不同而已。
    3.3.1 虚函数调用过程

    调用虚函数时,程序将查看存储在对象中的隐藏成员保存的虚函数表地址,然后转向相应的虚函数地址表。具体调用过程说明如下:

    • 如果使用类声明中定义的第一个虚函数,则程序将使用虚函数表中的第一个函数地址
    • 如果使用类声明中定义的第三个虚函数,则程序将使用地址为虚函数表中第三个元素的函数

    3.4 使用虚函数成本

    使用虚函数时,在内存和执行速度方面有一定的成本,包括:

    • 每个对象都将增大,增大量为存储地址的空间
    • 对于每个类,编译器都将创建一个虚函数地址表(数组)
    • 对于每个函数调用,都需要执行一项额外的操作,即到虚函数表中查找地址

    虽然非虚函数的效率比虚函数稍高,但不具备动态联编功能。

    四、虚函数注意事项

    虚函数的一些要点如下:

    (1)在基类方法的声明中使用关键字virtual,可使该方法在基类以及所有的派生类(包括从派生类派生出来的类)中是虚的。

    (2)如果使用指向对象的引用或指针来调用虚方法,程序将使用为对象类型定义的方法,而不是使用为引用或指针类型定义的方法。这称为动态联编或晚期联编。这种行为非常重要,因为这样基类指针或引用可以指向派生类对象。

    (3)如果定义的类将被用作基类,则应将哪些要在派生类中重新定义的类方法声明为虚方法。

    4.1 构造函数

    构造函数不能是虚函数。创建派生类对象时,将调用派生类的构造函数,而不是基类的构造函数,然后,派生类的构造函数将使用基类的一个构造函数,这种顺序不同于继承机制。因此,派生类不继承基类构造函数,所以将类构造函数声明为虚的没什么意义。

    4.2 析构函数

    析构函数应当是虚函数,除非类不用作基类。例如,假设Employee是基类,Singer是派生类,并添加一个char*成员,该成员指向由new分配的内存。当Singer对象过期时,必须调用~Singer()析构函数来释放内存。示例代码如下:

    Employee *pe = new Singer;
    delete pe;		// 使用~Employee()或~Singer()
    

    如果使用默认的静态联编(析构函数为非虚函数),delete语句将调用~Employee()析构函数。这将释放由Singer对象中的Employee部分指向的内存(应为delete pe;调用的是Employee类的析构函数),但不会释放新的类成员指向的内存。

    如果析构函数是虚函数,则delete pe;将先调用Singer()析构函数释放由Singer指向的内存,然后调用Employee()析构函数来释放由Employee组件指向的内存。

    注: 通常应给基类提供一个虚析构函数,即使它并不需要析构函数。

    4.3 友元函数

    友元函数不能是虚函数,因为友元函数不是类成员函数,而只有成员函数才能使虚函数。如果由于这个原因引起设计问题,可以通过让友元函数使用虚成员函数来解决。

    4.4 没有重新定义

    如果派生类没有重新定义函数,将使用该函数的基类版本。如果派生类位于派生链中,则将使用最新的虚函数版本。

    4.5 重新定义将隐藏方法

    假设有如下示例代码:

    // 基类
    class Base
    {
    public:
    	virtual void showperks(int a) const;    
    };
    
    // 派生类
    class Derived : public Base
    {
    public:
        virtual void showperks() const;
    };
    
    // 调用
    Derived der;
    der.showperks();		// 有效的调用
    der.showperks(5);		// 无效的调用
    

    新定义将showperks()定义为一个不接受任何参数的函数。重新定义不会生成函数的两个重载版本,而是隐藏了接受一个int参数的基类版本。总之,重新定义继承的方法并不是重载。

    如果在派生类中重新定义函数,将不只是使用参数列表相同的函数覆盖基类声明,无论参数列表是否相同,该操作将隐藏所有的同名基类方法

    这引出两条经验规则:

    (1)如果重新定义继承的方法,应确保与原来的原型完全相同,但如果返回类型是基类引用或指针,则可以修改为指向派生类的引用或指针。这种特性被称为返回类型协变(covariance of return type),因为允许返回类型随类类型的变化而变化。示例代码如下:

    // 基类
    class Base
    {
    public:
        virtual Base& build(int a);
    };
    
    // 派生类
    class Derived : public Base
    {
    public:
        // 返回类型协变的派生类方法
        virtual Derived& build(int a);
    };
    

    注: 这种例外只适用于返回值,而不适用于参数。

    (2)如果基类中声明的函数被重载了,则应在派生类中重新定义所有的基类重载函数。示例代码如下:

    // 基类
    class Base
    {
    public:
        // 3个showperks()重载函数
        virtual void showperks(int a) const;
        virtual void showperks(double b) const;
        virtual void showperks() const;
    };
    
    // 派生类
    class Derived : public Base
    {
    public:
        // 3个重新定义的showperks()重载函数
        virtual void showperks(int a) const;
        virtual void showperks(double b) const;
        virtual void showperks() const;
    };
    

    注: 如果只重新定义一个版本,则另外两个版本将被隐藏,派生类对象将无法使用它们。如果重新定义的基类中重载的某个函数不需要对函数行为进行修改,则派生类新定义的函数可只调用被新定义的基类函数,示例代码如下:

    void Derived::showperks() const
    {
        // 不更改showperks()行为,只需调用基类的相同版本函数即可
        Base::showperks();
    }
    
    展开全文
  • 动态联编说的是程序在运行时才确定调用和被调用者的关系.这个主要是虚函数实现的多态性. 1.静态联编 静态联编是指联编工作在编译阶段完成的,这种联编过程是在程序运行之前完成的,又称为早期联编。要实现...
    静态联编说的是在编译时就已经确定好了调用和被调用两者的关系
    动态联编说的是程序在运行时才确定调用和被调用者的关系.
    这个主要是虚函数实现的多态性.

    1.静态联编

    静态联编是指联编工作在编译阶段完成的,这种联编过程是在程序运行之前完成的,又称为早期联编。要实现静态联编,在编译阶段就必须确定程序中的操作调用(如函数调用)与执行该操作代码间的关系,确定这种关系称为束定,在编译时的束定称为静态束定。静态联编对函数的选择是基于指向对象的指针或者引用的类型。其优点是效率高,但灵活性差。


    1:静态联编

    #include"iostream.h"
    class A
    {
    public:
    	void fun()
    	{
    		cout << "A" << "";
    	}
    };
    
    class B : public A
    {
    public:
    	void fun()
    	{
    		cout << "B" << endl;
    	}
    };
    
    void main()
    {
    	A* pa = NULL;
    	A a;
    	B b;
    	pa = &a; pa->fun();
    	pa = &b; pa->fun();
    }

    该程序的运行结果为:A   A


    从例1程序的运行结果可以看出,通过对象指针进行的普通成员函数的调用,仅仅与指针的类型有关,而与此刻指针正指向什么对象无关要想实现当指针指向不同对象时执行不同的操作,就必须将基类中相应的成员函数定义为虚函数,进行动态联编。


    2.动态联编

    动态联编是指联编在程序运行时动态地进行,根据当时的情况来确定调用哪个同名函数,实际上是在运行时虚函数的实现。这种联编又称为晚期联编,或动态束定。动态联编对成员函数的选择是基于对象的类型,针对不同的对象类型将做出不同的编译结果。C++中一般情况下的联编是静态联编,但是当涉及到多态性和虚函数时应该使用动态联编。动态联编的优点是灵活性强,但效率低。


    动态联编规定:只能通过指向基类的指针或基类对象的引用来调用虚函数,

    其格式为:指向基类的指针变量名->虚函数名(实参表) 或  基类对象的引用名.虚函数名(实参表)


    实现动态联编需要同时满足以下三个条件:

     必须把动态联编的行为定义为类的虚函数。

     类之间应满足子类型关系,通常表现为一个类从另一个类公有派生而来。

    ③ 必须先使用基类指针指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。


    2:动态联编

    #include "iostream.h"
    class A
    {
    public:
    	Virtual void fun()   //虚函数
    	{
    		cout << "A" << "";
    	}
    };
    
    class B : public A
    {
    public:
    	Virtual void fun()    //虚函数
    	{
    		cout << "B" << endl;
    	}
    };
    
    void main()
    {
    	A* pa = NULL;
    	A a;
    	B b;
    	pa = &a; pa->fun();
    	pa = &b; pa->fun();
    }

    该程序的运行结果为:A  B


    从例2程序的运行结果可以看出,将基类A中的函数fun定义为虚函数后,当指针指向不同对象时执行了不同的操作,实现了动态联编。


    3.动态联编分析

       动态联编要求派生类中的虚函数与基类中对应的虚函数具有相同的名称、相同的参数个数和相同的对应参数类型、返回值或者相同,或者都返回指针或引用,并且派生类虚函数所返回的指针或引用的基类型是基类中虚函数所返回的指针或引用的基类型的子类型。如果不满足这些条件,派生类中的虚函数将丢失其虚特性,在调用时进行静态联编。


    3:通过指向基类的指针来调用虚函数

    #include"iostream.h"
    Class base
    {
    public:
    	virtual void fun1() { cout << "base fun1" << endl; }
    	virtual void fun2() { cout << "base fun2" << endl; }
    	void fun3() { cout << "base fun3" << endl; }
    	void fun4() { cout << "base fun4" << endl; }
    };
    Class derived : public base
    {
    public:
    	Virtual void fun1() { cout << "derived fun1" << endl; }
    	Virtual void fun2(intx) { cout << "derived fun2" << endl; }
    	Virtual void fun3() { cout << "derived fun3" << endl; }
    	Void fun4() { cout << "derived fun4" << endl; }
    };
    
    void main()
    {
    	base* pb;
    	derived d;
    	pb = &d;
    
    	//通过指向基类的指针来调用虚函数
    	pb->fun1();
    	pb->fun2();
    	pb->fun3();
    	pb->fun4();
    }

    该程序的运行结果:

    Derived fun1     base fun2      base fun3      base fun4


    本例中函数fun1在基类base和派生类derived中均使用了关键字virtual定义为虚函数,并且这两个虚函数具有相同的参数个数、参数类型和返回值类型。因此,当指针pb访问fun1函数时,采用的是动态联编。

    函数fun2在基类base和派生类de-rived中定义为虚函数,但这两个虚函数具有不同的参数个数。函数fun2丢失了其虚特性,在调用时进行静态联编。

    函数fun3在基类base中说明为一般函数,在派生类derived中定义为虚函数。在这种情况下,应该以基类中说明的成员函数的特性为标准,即函数fun3是一般成员函数,在调用时采用静态联编。

    函数fun4在基类base和派生类derived中均说明为一般函数,因此基类指针pb只能访问base中的成员。


    4:通过基类对象的引用来调用虚函数

    #include"iostream.h"
    Class CPoint
    {
    public:
    	CPoint(doublei,doublej) { x = i; y = j; }
    	Virtual double Area() { return 0.0; }
    private:
    	doublex,y;
    };
    
    Class CRectangle : public CPoint
    { public:
    	CRectangle(double i,double j,double k,double l);
    	Double Area() { return w*h; }
    private:
    	double w,h;
    };
    
    CRectangle::CRectangle(double i,double j,double k,double l) :CPoint(i, j)
    {
    	w = k;
    	h = l;
    }
    
    Void fun(CPoint &s)
    {
    	//通过基类对象的引用来调用虚函数
    	cout << s.Area() << endl;
    }
    
    void main()
    {
    	CRectangle rec(3.0, 5.2, 15.0, 25.0);
    	fun(rec);
    }

    该程序的运行结果为:375


    4中的成员函数Area在基类CPoint中使用了关键字virtual定义为虚函数,在派生类CRectangle中定义为一般函数,但是进行了动态联编,结果为15*25375。这是因为一个虚函数无论被公有继承多少次,它仍然保持其虚特性。在派生类中重新定义虚函数时,关键字virtual可以写也可不写,但为了保持良好的编程风格,避免引起混乱时,应写上该关键字


    4.小结

       从以上四个例子中可以看出:虚函数是实现多态的基础,是实现动态联编的必要条件之一动态联编要靠虚函数来实现,虚函数要靠动态联编的支持。两者相辅相成,缺一不可。


    展开全文
  • 先上一段代码帮助理解,由一个圆派生出一个球类,他们有一个公共...“静态联编输出结果:”<<endl; int main() { Globe globe(0,0,1);//这部分是随便初始化的三个实参 globe.shapeName();//输出名字globe cou...
    	先上一段代码帮助理解,由一个圆派生出一个球类,他们有一个公共的基类,这个基类是虚基类可以用virtual声明,只要有一个函数是虚函数,那么这个类就是抽象类。
    

    cout<<“静态联编输出结果:”<<endl;
    int main()
    {
    Globe globe(0,0,1);//这部分是随便初始化的三个实参
    globe.shapeName();//输出名字globe
    cout<<globe.getRadius()<<endl;
    cout<<globe.area()<<endl;//对象名.成员函数,这是静态多态,目的输出面积
    cout<<globe;
    //测试5
    //动态联编
    cout<<“动态联编输出结果:”<<endl;
    Shape *Glo;//Shape是抽象类,不能定义对象,里面只有虚函数,为后面的动态调用做伏笔
    Glo=&globe;//将球类的对象地址赋给指针变量Glo,初始化为指向基类型的指针变量
    Glo->shapeName();//动态输出
    cout<getRadius()<<endl;
    cout<area()<<endl;
    cout<volume();
    return 0;
    }
    看到这里,大家基本明白什么是动态多态和静态多态!在这里插入图片描述
    以上就是输出结果,中间涉及到<<字符的重载!

    展开全文
  • C++动态联编

    千次阅读 2020-04-02 21:31:09
    成为一个可执行程序)的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系,按照联编所进行的阶段不同,可分为静态联编动态联编。 静态联编 静态联编又...
  • 静态联编动态联编定义 将源代码中的函数调用解释为执行特定的函数代码块称为函数名联编。在C语言中,这非常简单,因为每个函数名都对应一个不同的函数。在C++中,由于函数重载的缘故,这项任务变得十分复杂。...
  • C++-动态联编

    2021-02-24 16:48:40
    静态联编 束定:程序中的操作调用(如函数调用)与执行该操作代码间的关系(简单来说就是在函调用时能找到相应代码的位置) 静态联编就是联编工作在编译阶段完成 也就是在程序运行之前就已经确定好了调用这个函数要...
  • ![图片说明](https://img-ask.csdn.net/upload/201612/09/1481297082_928864.png) ## **请问图中代码算不算动态联编,如果是的话具体是怎么实现的?如果不是的话又是为什么?**
  • C++ 动态联编实现原理分析

    千次阅读 2015-11-17 19:25:46
    C++标准并没有规定如何实现动态联编,但大多数的C++编译器都是通过虚指针(vptr)和虚函数表(vtable)来实现动态联编。 基本的思路是: (1)为每一个包含虚函数的类建立一个虚函数表,虚函数表的每一个表项...
  • C++动态联编与静态联编

    千次阅读 2013-06-11 13:15:29
    加入自己一些理解.... ...按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编动态联编。  1. 静态联编 静态联编是指联编工作在编译阶段完成的,这种联编过程是在程序运行之前
  • 先不论动态还是静态,首先需要明确的是关于“联编”的含义,书中有这样的说明: 将源代码中的函数调用解释为执行特定函数代码块被称为函数名联编(binding) 通俗些说,就是指明调用函数的语句调用的究竟是哪一个...
  • 按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编动态联编。 静态联编是指在编译阶段就将函数实现和函数调用关联起来,因此静态联编也叫早绑定,在编译阶段就必须了解所有的函数或模块执行所需要...
  • 文章目录C++的动态联编与虚函数前言指针和引用的兼容性静态联编与动态联编动态联编的缺点虚函数工作原理虚函数注意项总结 前言 函数名联编(binding):将源代码中的函数调用解释为执行特定的函数代码块的过程。 ...
  • 初学c++动态联编

    2017-12-24 16:49:00
    先看一下什么是C++联编? 我觉得通俗的讲,用对象来访问类的成员函数就是静态联编。 那什么是动态联编: 一般是通过虚函数实现动态联编。 看一个动态联编的例子: 我比较懒,所以直接粘贴了MOOC...
  • 动态多态(运行时多态、动态联编、晚绑定)例子1解释1例子2解释2去掉virtual的时候有virtual的时候向上类型转换(upcasting)4.虚函数虚函数的原理--虚函数表区分【virtual覆盖基类函数】与【派生类隐藏基类同名...
  • 多态性是C++最主要的特征,多态性的实现得益于C++中的动态联编技术。文章通过对动态联编的关键技术虚拟函数表进行深入的剖析,解析的动态联编的过程极其技术要领。
  • C++虚函数与动态联编

    2019-07-22 22:12:38
    动态联编与静态联编 1.动态联编与静态联编 联编就是将模块或者函数合并在一起生成可执行代码的处理过程,同时对每个模块或者函数调用分配内存地址,并且对外部访问也分配正确的内存地址,它是计算机程序彼此关联的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,155
精华内容 5,662
关键字:

c++动态联编