摘要】:本文阐述了静态联编和动态联编的概念和区别,通过具体实例分析了实现动态联编的条件,指出了虚函数是实现动态联编的基础。

【关键词】:静态联编;动态联编;虚函数

在C++中,联编是指一个计算机程序的不同部分彼此关联的过程。按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编和动态联编。

    1. 静态联编

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

例1:静态联编

#include"iostream.h"

class A

{public:

voidf(){cout<<"A"<<"";}

};

classB:publicA

{public:

voidf(){cout<<"B"<<endl;}

};

Void main()

{A*pa=NULL;

Aa;Bb;

pa=&a;pa->f();

pa=&b;pa->f();

}

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

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

2. 动态联编

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

动态联编规定,只能通过指向基类的指针或基类对象的引用来调用虚函数,其格式为:指向基类的指针变量名->虚函数名(实参表)或基类对象的引用名.虚函数名(实参表)

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

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

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

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

例2:动态联编

#include"iostream.h"

classA

{public:

Virtual voidf()//虚函数

{cout<<"A"<<"";}};

classB:publicA

{public:

Virtual voidf()//虚函数

{cout<<"B"<<endl;}

};

voidmain()

{ A*pa=NULL;

Aa;Bb;

pa=&a;

pa->f();

pa=&b;

pa->f();

}

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

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

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;

derivedd;

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*25即375。这是因为一个虚函数无论被公有继承多少次,它仍然保持其虚特性。在派生类中重新定义虚函数时,关键字virtual可以写也可不写,但为了保持良好的编程风格,避免引起混乱时,应写上该关键字。

4. 小结

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

转自:https://blog.csdn.net/neiloid/article/details/6934129

动态联编与静态联编的区别相关推荐

  1. Linux下动态库(.so)和静态库(.a) 的区别

    linux下有两种库:动态库和静态库(共享库) 二者的不同点在于代码被载入的时刻不同. 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大. 动态库(共享库)的代码在可执行程序运行时才载入内 ...

  2. C++ 调用lib 和 dll的 方法 及 动态库DLL与静态库lib的区别

    C++ 调用.lib的方法: 一: 隐式的加载时链接,有三种方法 1  LIB文件直接加入到工程文件列表中 在VC中打开File View一页,选中工程名,单击鼠标右键,然后选中"Add F ...

  3. C++的静态联编和动态联编

    联编的概念 联编是指一个计算机程序自身彼此关联的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系. 意思就是这个函数的实现有多种,联编就是把调用和 ...

  4. 静态联编与动态联编之virtual的作用

    =========================定义========================= 将一个调用函数连接上正确的被调用函数,这个过程就叫做函数的联编,简称联编.在C++中,一共有两 ...

  5. 关于静态联编和动态联编

    首先什么是联编? 通俗的来说联编就是函数调用(操作调用)与执行该操作(函数)的代码段之间的映射关系. 按照联编所进行的阶段不同可分为静态联编和动态联编 举个列子 #include<iostrea ...

  6. Cpp 对象模型探索 / 静态联编和动态联编

    一.源码 #include <iostream>class Father { public:Father(){/*** 该处直接将该对象清零,意味着虚函数表指针亦被清零.*/memset( ...

  7. 静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数

    1.静态联编,是程序的匹配,连接在编译阶段实现,也称为早期匹配.重载函数使用静态联编. 2.动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编.switch语句和if语句是动态联编的例子. #i ...

  8. c++中的多态---1(多态概念,静态联编和动态联编,多态原理解析,重载,重写,重定义的对比)

    多态的基本概念 多态是面向对象设计语言数据抽象和继承之外的第三个基本特征 多态性(polymorphism)提供接口与具体实现之间的另一层隔膜,从而将"what"和"ho ...

  9. C++静态联编与动态联编

    目录 基本概念 举个栗子 基本概念 联编 就是将模块或者函数合并在一起生成可执行代码的处理过程(函数调用),按照联编所进行的阶段不同,可分为两种不同的联编方式:静态联编和动态联编. 函数调用和实现的过 ...

最新文章

  1. 惊!史上最全的select加锁分析(Mysql)
  2. python b64 图片处理
  3. 【分享】怎样学习一门新技术?
  4. unix到底有啥用_观点|什么是Unix以及它为什么这么重要?
  5. vs2010 qt中文乱码 最终版
  6. Rust核心团队前成员Brian Anderson加入PingCAP
  7. 空投坐标怎么看6_嗦粉不咯?桂林米粉店将分三四五星级,你怎么看? 旅行 6 月 4 日热点速递...
  8. linux几种方式来弹哥shell
  9. CentOS 7使用yum安装MYSQL
  10. 阿里撬得动“印度版”抖音吗?
  11. 特征工程之特征选择(4)----嵌入法(Embed)
  12. 【程序员如何买基金 八】筛选优秀的债券基金
  13. 在物联网领域,英特尔除了高速计算的芯片,还提供了什么技术?
  14. 遗传算法(Genetic Algorithm)详解与实现
  15. 我对于测试团队建设的意见
  16. tomcat配置url跳转_架构成长之路:还不清楚原理就晚了,Java技术大咖带你手写Tomcat...
  17. ESP32-S3 LVGL http下载B站头像 JPG显示
  18. 澳大利亚史上最大数据泄露事件,40%的居民信息被泄露
  19. iPad Pro大猜想:预计秋季与iOS 9同步亮相
  20. UI组件库的引用方式

热门文章

  1. doc es 中type_Elasticsearch基础——概念和基本API操作
  2. 基于javaweb的红酒朔源管理系统(java+ssm+jsp+layui+jquery+mysql)
  3. 微信公众号实现智能聊天-接入第三方智能机器人平台
  4. JavaWeb学习笔记7
  5. linux C读取字库文件
  6. Firefox 检测到潜在的安全威胁,并因 www.baidu.com 要求安全连接而没有继续。
  7. 屁股决定脑袋的另外一层意思:走动式管理脑袋
  8. Radmin通过互联网联机
  9. 【Python】写一个程序,判断给定年份是否为闰年。
  10. 对比分析法、多维度拆解、辛普森悖论