动态链接和静态链接

来源:互联网 发布:淘宝漏发货的怎么处理 编辑:程序博客网 时间:2024/05/21 11:02

  在类的习惯性用法中,我们提到:对于类中代码量较多的成员函数,仅仅在头文件的类中声明成员和函数用法,而将方法封装起来。

  对于代码量较大的成员函数来说,直接把代码放在类中定义存在两个问题:一是使用起来很不方便,二是破坏了信息隐藏机制。

  那么为什么说将代码放在类中定义会破坏信息隐藏机制呢?

  实际上,对于变量和函数,一般在头文件里面都只会做一个声明,来告诉使用者参数的意义和函数的用法,而并不公布源码,利用类的封装特性,对外只提供一个借口来供程序猿使用来达到非开源的目的。一般会将函数部分封装在dll文件中。

  类文件很多存在于头文件中,方便使用者使用。但是在头文件,也就是类内部,即使是出于开源的动机,也最好不要在头文件(类里面)进行实现。为什么?我们分为两种情况:

  1、在头文件中实现函数体,如果在头文件中实现一个函数体,那么如果在多个C文件中引用它,而且又同时编译多个C文件,将其生成的目标文件连接成一个可执行文件,在每个引用此头文件的C文件所生成的目标文件中,都有一份这个函数的代码,如果这段函数又没有定义成局部函数(工作域发生冲突),那么连接到库的时候,就会发现多个相同的函数,就会报错。

  2、如果在头文件中定义全局变量,并且将此全局变量赋初值,那么在多个引用此头文件的C文件中同样存在相同变量名的拷贝,关键是此变量被赋了初值,所以编译器就会将此变量放入DATA段,最终在连接阶段,会在DATA段中存在多个相同的变量,它无法将这些变量统一成一个变量,也就是仅为此变量分配一个空间,而不是多份空间,假定这个变量在头文件没有赋初值,编译器就会将之放入BSS段,连接器会对BSS段的多个同名变量仅分配一个存储空间。

  关于text段、data段、bss段的说明另见博文

  那么这些函数最后仅仅在类中声明和告诉程序猿使用方法,那具体的实现方法放在哪里呢?

  有两种存放实现方法的文件,一种是以lib为后缀的文件,一种是以dll为后缀的文件。

  首先介绍以lib为后缀的文件,C++中的lib文件主要有两类,一种是静态的编译链接,叫座静态链接库,里面是货真价实的函数的实现;另一种是动态的编译链接,和dll一起联用。因为有动态链接的lib的存在,所以并不是所有的lib文件都是静态链接的。

  ●如何使用生成的lib文件

  为了可以使用.lib文件,我们需要刚刚生成的.lib文件,以及它所对应的头文件.h,因为.lib文件无法直接访问,且无法得知其接口,因此需要对应的头文件。假设现在有一个工程需要使用该lib文件,首先需要在工程属性中将.h文件的路径设置好,在文件中使用#include将头文件包含,然后对于lib文件,需要在工程属性中,设置其路径(或者直接放在工程文件的目录下,因为工程查找文件时是以工程文件所在路径为相对路径查找),然后类似opencv一样,在项目属性中,linker->input中输入要使用的lib名(或者使用program**,在文件中用语句将其写入(推荐)),这样配置就结束了。

  ●lib文件如何起作用

  当工程在编译的时候,系统就会将lib中的函数的实现插入到生成的exe中,从而完成其作用,因此我们知道,当lib很大的时候,最后生成的exe文件会相当的大,因为将需要的lib都加载到了最终的exe中。

  ●如何生成dll文件以及动态链接中的lib文件

  DLL文件被称为动态链接库。我们可以通过使用工程建立他们,在建立的时候首先建立一个空项目,然后将输出设置成dll,然后在主函数前使用***,意思是将该文件函数以dll文件导出,然后编译后生成了.lib文件和dll文件,其中的dll文件就是动态链接库,但是要注意这里的.lib文件就是上面所说的另一种lib文件,不同于静态链接库的lib文件(静态库的lib文件中货真价实的是函数的实现),该lib文件中没有函数的实现,而也是一些定义以及配置,真正的函数的实现存在于dll文件中。

  ●如何使用动态链接中的lib和dll文件

  要想使用dll文件,需要其对应的头文件(.h文件),lib以及dll,前两者的使用方法和静态是一样的,后者放在exe同一目录下就可以了。

  ●lib和dll的区别在IDE编译代码、运行程序中的异同

  1、单独的没有dll的lib是编译的时候用到的,而dll是运行时用到的。无论是静态的还是动态的,都有:如果仅仅要完成源代码的编译,仅仅需要lib。在有dll的情况下,如果要使动态链接的程序运行起来,只需要dll。

  2、如果是有dll文件的lib,一般是一些索引文件,记录了dll中函数的入口和位置(涉及内存地址的信息),dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来,索引和实现都在其中。使用静态编译的lib文件,在运行程序中不需要再挂动态库,缺点是导致应用程序比较大,而且丢失了动态库的灵活性,发布新版本时要发布新的应用程序才行。

  3、动态链接的情况下,有两个文件:一个是lib文件,一个是lib文件。lib文件包含被dll导出的函数名称和位置,dll包含实际的函数和数据,应用程序使用lib文件链接到dll文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是dll中相应函数代码的地址,从而节省了内存资源。dll和lib文件必须随应用程序一起发行,否则应用程序会发生错误。如果不能用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。

  ●使用lib的方法:
  静态lib中,一个lib文件实际上是任意个obj文件的集合,obj文件是cpp文件编译生成的。在编译这种静态库工程时,根本不会遇到链接错误;即使有错,也只会在使用这个lib的EXT文件或者DLL工程里暴露出来。
  在VC中新建一个static library类型的工程Lib,加入test.cpp文件和test.h文件(头文件内包括函数声明),然后编译,就生成了Lib.lib文件。
别的工程要使用这个lib有两种方式:
(1)在project->link->Object/Library Module中加入Lib.lib文件(先查询工程目录,再查询系统Lib目录);或者在源代码中加入指令#pragma comment(lib, “Lib.lib”)。
(2)将Lib.lib拷入工程所在目录,或者执行文件生成的目录,或者系统Lib目录中。
(3)加入相应的头文件test.h



0 0
原创粉丝点击