C++中的内部连接与外部连接(一)

类别:编程语言 点击:0 评论:0 推荐:
内部连接与外部连接(上)

SpitFire原创,CSDN首发,转贴请说明出处,谢谢。

欢迎大家来这里讨论问题 http://www.allaboutprogram.com/bb/index.php

 

在说内部连接与外部连接前,先说明一些概念。

 

1.声明

    一个声明将一个名称引入一个作用域;

       在c++中,在一个作用域中重复一个声明是合法的

      

       以下都是声明:

       int foo(int,int);           //函数前置声明

       typedef int Int;               //typedef 声明

       class bar;                      //类前置声明

       extern int g_var;           //外部引用声明

       class bar;                      //类前置声明

       typedef int Int;               //typedef 声明

       extern int g_var;           //外部引用声明

       friend test;                      //友员声明

       using std::cout;        //名字空间引用声明

       friend test;                      //友员声明

       using std::cout;              //名字空间引用声明

       int foo(int,int);           //函数前置声明

      

       在同一个作用域中你可以多次重复这些声明。

      

       有两种声明不能重复,那就是类成员函数及静态数据成员的声明

      

       class foo

       {

       static int i;

       static int i;//不可以

       public:

       int foo();

       int foo();//不可以

       };

 

2.定义

       一个定义提供一个实体(类型、实例、函数)在一个作用域的唯一描述。

       在同一作用域中不可重复定义一个实体。

       以下都是定义。

       int y;

       class foo {...};

       struct bar {...};

       foo* p;

       static int i;

       enum Color{RED,GREEN,BLUE};

       const double PI = 3.1415;

       union Rep{...};

       void test(int p) {};

       foo a;

       bar b;

3.编译单元

       当一个c或cpp文件在编译时,预处理器首先递归包含头文件,形成一个含有所有       必要信息的单个源文件,这个源文件就是一个编译单元。这个编译单元会被编译成为一个与cpp文件名同名的目标文件(.o或是.obj)。连接程序把不同编译单元中产生的符号联系起来,构成一个可执行程序。

4.自由函数

       如果一个函数是自由函数,那么这个函数不是类的成员函数,也不是友元函数。

 

下面来看内部连接和外部连接

       内部连接:如果一个名称对于它的编译单元来说是局部的,并且在连接时不会与其它编译单元中的同样的名称相冲突,那么这个名称有内部连接(注:有时也将声明看作是无连接的,这里我们统一看成是内部连接的)。

      

       以下情况有内部连接:

       a)所有的声明

       b)名字空间(包括全局名字空间)中的静态自由函数、静态友元函数、静态变量的定义

       c)enum定义

       d)inline函数定义(包括自由函数和非自由函数)

       e)类的定义

       f)名字空间中const常量定义

       g)union的定义

      

      外部连接:在一个多文件程序中,如果一个名称在连接时可以和其它编译单元交互,那么这个名称就有外部连接。

       以下情况有外部连接:

       a)类非inline函数总有外部连接。包括类成员函数和类静态成员函数

       b)类静态成员变量总有外部连接。

       c)名字空间(包括全局名字空间)中非静态自由函数、非静态友元函数及非静态变量

      

       下面举例说明:

       a)声明、enum定义、union定义有内部连接

所有的声明、enum定义及union定义在编译后不会产生连接符号,也就是在不同编译单元中有相同名称的声明及enum、union定义并不会在连接时发生发现多个符号的错误。

              // main.cpp

              typedef int Int;                //typedef 声明,内部连接

              enum Color{red};           //enum定义,内部连接

              union X                          //union定义,内部连接

              {

                     long a;

                     char b[10];

              };

              int main(void)

              {

                     Int i = red;

                     return i;

              }

             

              // a.cpp

              typedef int Int;         //在a.cpp中重声明一个int类型别名,在连接时不会发生错误

              enum Color{blue};   //在a.cpp中重定义了一个enum Color,在连接时不会发生错误

              const Int i =blue;                    //const常量定义,内部连接

              union X                                 //union定义,内部连接

              {

                     long a;

                     char b[10];

              };

       b)名字空间中静态自由函数、静态友元函数、静态变量、const常量定义有内部连接

             

              // main.cpp

              namespace test

              {

                     int foo();                             //函数声明,内部连接

                     static int i = 0;                         //名字空间静态变量定义,内部连接

                     static int foo() { return 0;}       //名字空间静态函数定义,内部连接

              }

              static int i = 0;                              //全局静态变量定义,内部连接

              static int foo() {return 1;}          //全局静态函数定义,内部连接

              const int k = 0;                      //全局const常量定义,内部连接

              int main(void)

              {

                     return 0;

              }

             

              //a.cpp

              namespace test

              {

                     int i = 0;                              //名字空间变量定义,外部连接

                     int foo() {return 0;}                   //名字空间函数定义,外部连接

              }

              int i = 0;                                       //全局变量定义,外部连接

              int k = 0;                                       //全局变量定义,外部连接

              int foo() { return 2;}                     //全局函数定义,外部连接

             

在全局名字空间中,main.cpp中定义了静态变量i,常量k,及静态自由函数foo等,这些都有内部连接。如果你将这些变量或函数的static或是const修饰符去掉,在连接时就会现multiply defined symbols错误,它们与a.cpp中的全局变量、全局函数发生冲突。

 

本文地址:http://com.8s8s.com/it/it28943.htm