精华内容
下载资源
问答
  • 动态联编

    千次阅读 多人点赞 2015-10-08 20:38:37
    关于 动态联编 和 静态联编 这个概念,自己听了老师上课讲的课仍然没有明白原理。 那么既然这样,只能自己去学习了。 首先我们知道的是,动态联编 和 静态联编 都是多态性的一种体现。 关于面向对象...

    关于 动态联编 和 静态联编 这个概念,自己听了老师上课讲的课仍然没有明白原理。

    那么既然这样,只能自己去学习了。


    首先我们知道的是,动态联编 和 静态联编 都是多态性的一种体现。

    关于面向对象的三个基本要素:封装(类型抽象), 继承 和 多态。

    首先我们从概念性上面了解了 动态联编 和 静态联编 的功能:实现了多态性。


    然后我们从最最基本的开始讲解。


    1.什么是 联编?

    我参考了下面这个博客:

    http://bdxnote.blog.163.com/blog/static/8444235200911311348529/


    联编是指一个计算机程序自身彼此关联的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系;按照联编所进行的阶段不同,可分为静态联编和动态联编;

    仔细读读红色字体的那部分句子。我们就能很清楚的明白什么是联编了。给大家举个最通俗易懂的例子好了:

    A类中有fun这个函数, B类中也有fun这个函数,现在我在类外的main函数里面调用fun 函数。

    那么main函数就是函数调用,调用fun函数,

    而A类中的fun函数和B类中的fun函数就是执行该操作的代码段

    所以现在联编就是实现两者的映射关系。

    1. class A  
    2. {     
    3.     void func() {cout<<"It's A"<<endl;  
    4.   
    5. };  
    6.   
    7. class B  
    8. {     
    9.     void func() {cout<<"It's B"<<endl;  
    10.   
    11. };  
    12. int main()  
    13. {  
    14.     func();  
    15. }  
    联编就是决定将main函数中的func()的函数调用映射到A中的func函数还是B中的func函数的过程。


    2.静态联编 和 动态联编 的定义

    知道了什么事联编,那么再来理解动态联编 和静态联编也就不难了

    静态联编:
    是指联编工作是在程序编译连接阶段进行的,这种联编又称为早期联编;因为这种联编是在程序开始运行之前完成的;
    在程序编译阶段进行的这种联编又称静态束定;在编译时就解决了程序中的操作调用与执行该操作代码间的关系,确定这种关系又被称为束定;编译时束定又称为静态束定;

    拿上面的例子来说,静态联编就是在编译的时候就决定了main函数中调用的是A中的func还是B中的func。一旦编译完成,那么他们的映射关系就唯一确定了。


    动态联编:
    编译程序在编译阶段并不能确切地知道将要调用的函数,只有在程序执行时才能确定将要调用的函数,为此要确切地知道将要调用的函数,要求联编工作在程序运行时进行,这种在程序运行时进行的联编工作被称为动态联编,或动态束定,又叫晚期联编;C++规定:动态联编是在虚函数的支持下实现的;

    动态联编在编译的时候还是不知道到底应该选择哪个func函数,只有在真正执行的时候,它才确定。


    静态联编和动态联编都是属于多态性的,它们是在不同的阶段进对不同的实现进行不同的选择;

    其实多态性的本质就是选择。因为存在着很多选择,所以就有了多态。


    3.静态联编

    首先还是拿个例子来说事吧。

    1. #include <iostream>  
    2. using namespace std;  
    3. class shape{  
    4.   public:  
    5.     void draw(){cout<<"I am shape"<<endl;}  
    6.     void fun(){draw();}  
    7. };  
    8. class circle:public shape{  
    9.   public:  
    10.     void draw(){cout<<"I am circle"<<endl;}  
    11. };  
    12. void main(){  
    13.     circle  oneshape;  
    14.     oneshape.fun();  
    15. }  
    现在我们详细具体定义了一开始的A类和B类以及func函数 。让我们来分析一下:

    调用oneshape.fun()的时候,进入类shape中的fun函数。

    现在我们的问题就是:fun函数调用的draw到底是shape里面的draw还是circle中的draw??

    答案是:它调用了cshape这个基类的draw函数。所以输出了 I am shape

    那么一直困扰我的问题是:为什么调用基类的draw而不是派生类中得draw呢?

    书上好像没有具体讲,上课的时候老师那也根本不会讲。

    自己想了一下,应该可以从汇编的角度理解:

    1.调用oneshape.fun()这里是一个跳转指令,进入类shape中的fun函数所在的代码段

    2.类shape的代码段是依次顺序放置的。进入fun函数后,现在我们要调用draw的地址。

    由于没有另外的数据结构来保存draw的地址,所以程序所知道的,必然只有在shape类中的draw地址了,仅仅用一个跳转指令

    在我的vs2010的反汇编调试窗口下是这样的一句代码:

    013B1546  call        shape::draw (13B10F5h) 

    很明确这里指出了shape::draw,也就确定了映射关系,完成了联编。


    4.动态联编

    从第3节中我们看到了静态联编的不足( 大概教材中就是这样说的 )。

    刚才我讲了,

    由于没有另外的数据结构来保存draw的地址,所以程序所知道的,必然之后在shape类中的draw地址了,仅仅用一个跳转指令

    所以我们想实现动态编联,其实就是想弄出个数据结构来,这个数据结构用来存放  映射关系,也就是联编。

    所以c++才搞了个虚函数。其实虚函数的本质就是搞了个数据结构。也就是虚函数表

    关于虚函数表,自己不想多扯了,扯出来又是一大串,大家自己去下面的博客学习吧。

    http://blog.csdn.net/haoel/article/details/1948051/

    4.1虚函数

    大家都不喜欢理解概念。我也不喜欢。但是概念毕竟是要紧的。我已经跟大家说明了为什么要引入虚函数。所以接下来请大家耐心看看下面这段概念吧:

    虚函数是动态联编的基础;虚函数是成员函数,而且是非静态的成员函数;虚函数在派生类中可能有不同的实现,当使用这个成员函数操作指针或引用所标识的对象时,对该成员函数的调用采用动态联编方式,即:在程序运行时进行关联或束定调用关系;
    动态联编只能通过指针或引用标识对象来操作虚函数;如果采用一般的标识对象来操作虚函数,将采用静态联编的方式调用虚函数;
    如果一个类具有虚函数,那么编译器就会为这个类的对象定义一个指针成员,并让这个指针成员指向一个表格,这个表格里面存放的是类的虚函数的入口地址;比如:一个基类里面有一些虚函数,那么这个基类就拥有这样一个表,它里面存放了自己的虚函数的入口地址,其派生类继承了这个虚函数表,如果在派生类中重写/覆盖/修改了基类中的虚函数,那么编译器就会把虚函数表中的函数入口地址修改成派生类中的对应虚函数的入口地址;这就为类的多态性的实现提供了基础;

    虚函数按照其声明顺序存放于虚函数表中;
    父类的虚函数存放在子类虚函数的前面;
    多继承中,每个父类都有自己的虚函数表;
    子类的成员函数被存放于第一个父类的虚函数表中;

    4.2动态联编举例

    最后给大家举个例子,在第三节的那个例子上,下面的代码仅仅是多了一个词:virtual

    1. #include <iostream>  
    2. using namespace std;  
    3. class shape{  
    4.   public:  
    5.     void virtual draw(){cout<<"I am shape"<<endl;}//这里设定了draw是虚函数  
    6.     void fun(){draw();}  
    7. };  
    8. class circle:public shape{  
    9.   public:  
    10.     void draw(){cout<<"I am circle"<<endl;}//虽然没有说明circle类中的draw是虚函数,但是circle其实继承了virtual性质  
    11. };  
    12. void main(){  
    13.     circle  oneshape;  
    14.     oneshape.fun();  
    15. }  
    现在我们再来运行一下程序,输出就变成 了I am circle

    这里的反汇编代码贴出来,自己有空看看:

    [plain]  view plain copy print ?
    1. 00CC15A0  push        ebp    
    2. 00CC15A1  mov         ebp,esp    
    3. 00CC15A3  sub         esp,0CCh    
    4. 00CC15A9  push        ebx    
    5. 00CC15AA  push        esi    
    6. 00CC15AB  push        edi    
    7. 00CC15AC  push        ecx    
    8. 00CC15AD  lea         edi,[ebp-0CCh]    
    9. 00CC15B3  mov         ecx,33h    
    10. 00CC15B8  mov         eax,0CCCCCCCCh    
    11. 00CC15BD  rep stos    dword ptr es:[edi]    
    12. 00CC15BF  pop         ecx    
    13. 00CC15C0  mov         dword ptr [ebp-8],ecx    
    14. 00CC15C3  mov         eax,dword ptr [this]    
    15. 00CC15C6  mov         edx,dword ptr [eax]    
    16. 00CC15C8  mov         esi,esp    
    17. 00CC15CA  mov         ecx,dword ptr [this]    
    18. 00CC15CD  mov         eax,dword ptr [edx]    
    19. 00CC15CF  call        eax    
    20. 00CC15D1  cmp         esi,esp    
    21. 00CC15D3  call        @ILT+440(__RTC_CheckEsp) (0CC11BDh)    
    22. 00CC15D8  pop         edi    
    23. 00CC15D9  pop         esi    
    24. 00CC15DA  pop         ebx    
    25. 00CC15DB  add         esp,0CCh    
    26. 00CC15E1  cmp         ebp,esp    
    27. 00CC15E3  call        @ILT+440(__RTC_CheckEsp) (0CC11BDh)    
    28. 00CC15E8  mov         esp,ebp    
    29. 00CC15EA  pop         ebp    
    30. 00CC15EB  ret    
    展开全文
  • 本文阐述了静态联编和动态联编的概念和区别,通过具体实例分析了实现动态联编的条件,指出了虚函数是实现动态联编的基础。
  • 主要介绍了C++的静态联编和动态联编详解,对于深入理解C++编译运行原理有很大帮助,需要的朋友可以参考下
  • 静态联编和动态联编

    2019-05-05 15:49:57
    静态联编和动态联编 1、联编是指一个程序模块、代码之间互相关联的过程。 2、静态联编(static binding),是程序的匹配、连接在编译阶段实现,也称为早期匹配。 重载函数使用静态联编。(没有加virtual) 3、...

    理论:

    静态联编和动态联编

    1、联编是指一个程序模块、代码之间互相关联的过程。

    2、静态联编(static binding),是程序的匹配、连接在编译阶段实现,也称为早期匹配。

        重载函数使用静态联编。(没有加virtual

    3、动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编(迟绑定)。(加了virtual)

    switch 语句和 if 语句是动态联编的例子。

    实例

    #include <iostream>
    using namespace std;
    class A
    {
    private:
        int a;
    public:
        virtual void print()
        {
            cout << "a=" << a << endl;
        }
        A(int a)
        {
            this->a = a;
        }
    };
    class B : public A
    {
    private:
        int b;
    public:
        virtual void print()
        {
            cout << "b=" << b << endl;
        }
        B(int a, int b) : A(a)
        {
            this->b = b;
        }
    };

    void main()
    {
        
        A a1(1);
        B b1(2,3);    
        A *base1 = NULL;
        base1 = &a1;
        base1->print();   //1
        A *base2 = NULL;
        base2 = &b1;
        base2->print();   //3
        
        A &base3 = a1;
        base3.print();  //1
        A &base4 = b1;
        base4.print();  //  3

        system("pause");
    }

    4、理论联系实际

         在没有加virtual之前

    1、C++与C相同,是静态编译型语言

    2、在编译时,编译器自动根据指针的类型判断指向的是一个什么样的对象;所以编译器认为父类指针指向的是父类对象。

    3、由于程序没有运行,所以不可能知道父类指针指向的具体是父类对象还是子类对象

    从程序安全的角度,编译器假设父类指针只指向父类对象,因此编译的结果为调用父类的成员函数。这种特性就是静态联编。

        加上 virtual  动态联编,根据实际的类型执行相应的函数(父类还是子类的函数)

    此篇文章的前序:https://blog.csdn.net/huang1600301017/article/details/89819702

    展开全文
  • c++ 联编:是描述编译器决定在程序运行时,一个函数调用应执行哪...动态联编:编译程序在编译阶段并不能确切知道将要调用的函数,只有在程序运行时才能确定将要调用的函数,为此要确切知道该调用的函数,要求联编工...

    c++

    联编:是描述编译器决定在程序运行时,一个函数调用应执行哪段代码的一个术语,它把一个标识符与一个存储地址联系起来。

    静态联编:在编译时所进行的这种联编又称静态束定,在编译时就解决了程序中的操作调用与执行该操作代码间的关系。(范围很大,比静态多态大)。

    动态联编:编译程序在编译阶段并不能确切知道将要调用的函数,只有在程序运行时才能确定将要调用的函数,为此要确切知道该调用的函数,要求联编工作要在程序运行时进行,这种在程序运行时进行联编工作被称为动态联编。

    多态:多态就是“多种形态”的意思。它是面向对象程序设计的一个重要特征。

    多态性:同样的消息被不同类型的对象接收时导致的不同行为。

    静态多态:在程序编译时就能确定调用哪一个函数,普通指函数的重载(包括运算符重载)

    动态多态:在程序编译时不能确定调用哪一个函数,只有在程序运行时才能确定调用哪一个函数。它与继承、虚函数有关。

    多态与联编的关系:多态是基于联编实现的,除了多态,还有其他的很多特性也是基于联编实现的。

    展开全文
  • C++ 静态联编 VS 动态联编 在编译过程中进行联编被称为静态联编。 在运行过程中进行联编被称为动态联编,包含虚函数的需要进行动态联编,编译器需要在程序运行时选择正确的虚方法的代码。 ...

    C++ 静态联编 VS 动态联编
    在编译过程中进行联编被称为静态联编。
    在运行过程中进行联编被称为动态联编,包含虚函数的需要进行动态联编,编译器需要在程序运行时选择正确的虚方法的代码。

    展开全文
  • 动态联编和静态联编

    2021-03-08 15:55:44
    动态联编和静态联编 一、静态联编 定义 在编译时所进行的这种联编又称静态束定,在编译时就解决了程序中的操作调用与执行该操作代码间的关系。 注意: 静态联编由可访问属性和默认值确定 二、动态联编 定义 编译...
  • 静态联编和动态联编1、联编是指一个程序模块、代码之间互相关联的过程。 2、静态联编(static binding),是程序的匹配、连接在编译阶段实现,也称为早期匹配。 重载函数使用静态联编。 3、动态联编是指程序联编...
  • 动态联编/运行时联编和静态联编 联编:将一个调用函数者连接上正确的被调用函数,这一过程叫做函数联编,一般简称为联编。动态联编(加virtual):预先不知道调用那个对象的函数,运行时动态的选择调用那个对象...
  • 摘要】:本文阐述了静态联编和动态联编的概念和区别,通过具体实例分析了实现动态联编的条件,指出了虚函数是实现动态联编的基础。 【关键词】:静态联编;动态联编;虚函数 在C++中,联编是指一个计算机...
  • 静态联编与动态联编

    千次阅读 2018-08-05 00:47:26
    将模板或者函数合并在一起生成可执行代码的处理过程(函数调用),按照联编进行的时间不同,可分为两种不同的联编方法:静态联编和动态联编。简单来理解,联编就是处理函数调用的过程 1)编译阶段进行的就是静态联...
  • 动态联编:使用虚函数时,程序使用那一个函数是不能在编译时确定的,因为编译器不知道用户选择的那种类型对象。 所以,编译器必须能够在程序运行时选择正确的虚方法的代码,这被称为动态联编,又称晚期联编 一、指针...
  • 动态联编与静态联编

    2016-08-15 10:29:58
    首先,联编是指一个计算机程序的不同部分彼此关联的过程。 静态联编是指联编工作在编译阶段完成的,这种联编过程是在程序运行之前完成的,又称为早期联编。要实现静态联编,在编译阶段就必须确定程序中...动态联编
  • 动态联编与静态联编的区别

    千次阅读 2019-03-18 14:40:57
    摘要】:本文阐述了静态联编和动态联编的概念和区别,通过具体实例分析了实现动态联编的条件,指出了虚函数是实现动态联编的基础。 【关键词】:静态联编;动态联编;虚函数 在C++中,联编是指一个计算机程序的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 19,601
精华内容 7,840
关键字:

动态联编