动态联编 和 静态联编

http://blog.youkuaiyun.com/gaoxin1076/article/details/8298279
转自
自己总结添加了一些东西方便自己复习!

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

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

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

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

1.什么是 联编?

我参考了下面这个博客:
http://bdxnote.blog.163.com/blog/static/8444235200911311348529/

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

例如

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

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

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

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


class A  
{     
    void func() {cout<<"It's A"<<endl;  

};  

class B  
{     
    void func() {cout<<"It's B"<<endl;  

};  
int main()  
{  
    func();  
}  

联编就是决定将main函数中的func()的函数调用映射到A中的func函数还是B中的func函数的过程。

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

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

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

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

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

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

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

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

3.静态联编

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

#include <iostream>  
using namespace std;  
class shape{  
  public:  
    void draw(){cout<<"I am shape"<<endl;}  
    void fun(){draw();}  
};  
class circle:public shape{  
  public:  
    void draw(){cout<<"I am circle"<<endl;}  
};  
void main(){  
    circle  oneshape;  
    oneshape.fun();  
}  

现在我们详细具体定义了一开始的A类和B类以及func函数。让我们来分析一下:
调用oneshape.fun()的时候,进入类shape中的fun函数。

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

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

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

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

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

  1. 1.调用oneshape.fun(),这里是一个跳转指令,进入类shape中的fun函数所在的代码段
  2. 2.类shape的代码段是依次顺序放置的。进入fun函数后,现在我们要调用draw的地址。
  3. 由于没有另外的数据结构来保存draw的地址,所以程序所知道的,必然只有在shape类中的draw地址了,仅仅用一个跳转指令
  4. 在我的vs2010的反汇编调试窗口下是这样的一句代码: 013B1546 call shape::draw
    (13B10F5h)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YULIU_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值