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

王朝c/c++·作者佚名  2006-01-09
宽屏版  字体: |||超大  

内部连接与外部连接(上)

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中的全局变量、全局函数发生冲突。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有