`
fujinbing
  • 浏览: 233301 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

C++中的内部链接和外部链接

    博客分类:
  • c++
阅读更多

c++中的内部连接与外部连接

Apr 22nd, 2007 by king

 

一.在学习内部连接与外部连接之前,必须先弄清楚几个概念:
1.声明
一个声明将一个名称引入一个作用域。在c++中,在一个作用域中重复一个声明是合法的。
以下都是声明:

 

int foo(int,int); //函数前置声明
typedef int Int; //typedef 声明
class bar; //类前置声明
extern int g_var; //外部引用声明
friend test; //友员声明
using std::cout; //名字空间引用声明
在同一作用域中可以多次重复以上声明,但是有两种声明是不能重复的,那就是类成员函数及静态数据成员的声明:

 

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; //定义一个double型常量
union Rep{…}; //定义一个联合
void test(int p) {}; //定义一个函数
foo a; //定义一个类实例
bar b; //定义一个结构体实例

 

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

 

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

 

二.内部连接和外部连接
1.内部连接:如果一个名称对于它的编译单元来说是局部的,并且在连接时不会与其它编译单元中的同样的名称相冲突,那么这个名称有内部连接(注:有时也将声明看作是无连接的,这里我们统一看成是内部连接的)。
以下情况有内部连接:
a)所有的声明
b)名字空间(包括全局名字空间)中的静态自由函数、静态友元函数、静态变量的定义
c)enum定义
d)inline函数定义(包括自由函数和非自由函数)
e)类的定义
在类中直接定义的函数相当于你写inline,这个叫做隐式内联,但是,不管是显示内联还是隐式内联,都只是给编译器一个请求,最后是否被判断成内联,还得看你的功能模块的复杂度来决定的。故不会发生类重复定义问题。
f)名字空间中const常量定义
g)union的定义

 

2.外部连接:在一个多文件程序中,如果一个名称在连接时可以和其它编译单元交互,那么这个名称就有外部连接。
以下情况有外部连接:
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中的全局变量、全局函数发生冲突。

分享到:
评论

相关推荐

    c++内部链接与外部链接

    对内部链接和外部链接的详解,理解下很有用

    【C++】多文件程序结构.pdf

    链接性分为内部链接和外部链接。 外部链接:外部链接的定义可被定义所处的翻译单元(.cpp)内看见,也可以被其他翻译单元引⽤。 具有外部链接性的: · ⾮inline函数。包括命名空间中⾮静态函数、类成员函数和类静态...

    新手学习C++入门资料

    输入和输出是通过C++类来实现的,cin和cout是这些类的实例,他们是在C++语言的外部实现。 在C++语言中,有了一种新的注释方法,就是‘//’,在该行//后的所有说明都被编译器认为是注释,这种注释不能换行。C++中...

    c++关键字分析

    整理c++const static关键字和内外部链接属性

    Visual C++ 2005入门经典.part08.rar (整理并添加所有书签)

    19.7.6 链接订单对话框和客户对话框 19.7.7 练习使用数据库查看器 19.8 小结 19.9 练习题 第20章 更新数据源 20.1 更新操作 20.1.1 CRecordset更新操作 20.1.2 事务 20.2 简单的更新示例 20.3 管理更新过程 20.4 向...

    Visual C++ 2005入门经典.part04.rar (整理并添加所有书签)

    19.7.6 链接订单对话框和客户对话框 19.7.7 练习使用数据库查看器 19.8 小结 19.9 练习题 第20章 更新数据源 20.1 更新操作 20.1.1 CRecordset更新操作 20.1.2 事务 20.2 简单的更新示例 20.3 管理更新过程 20.4 向...

    Visual C++ 2005入门经典.part05.rar (整理并添加所有书签)

    19.7.6 链接订单对话框和客户对话框 19.7.7 练习使用数据库查看器 19.8 小结 19.9 练习题 第20章 更新数据源 20.1 更新操作 20.1.1 CRecordset更新操作 20.1.2 事务 20.2 简单的更新示例 20.3 管理更新过程 20.4 向...

    Visual C++ 2005入门经典--源代码及课后练习答案

    本书延续了Ivor Horton讲解编程语言的独特方法,从中读者可以学习Visual C++ 2005的基础知识,并全面掌握在MFC和Windows Forms中访问数据源的技术。此外,本书各章后面的习题将有助于读者温故而知新,并尽快成为C++...

    Visual C++ 2010入门经典(第5版)--源代码及课后练习答案

    《visual c++ 2010入门经典(第5版)》针对visual c++ 2010版本进行了全面更新,介绍了最新的开发环境和如何使用visual c++构建现实世界中的应用程序。拥有本书,您就迈向了通往使用两种c++版本编写应用程序的成功之路...

    visualC++2010入门经典源代码

    2.5 c++中的计算 54 2.5.1 赋值语句 54 2.5.2 算术运算 55 2.5.3 计算余数 59 2.5.4 修改变量 60 2.5.5 增量和减量运算符 60 2.5.6 计算的顺序 63 2.6 类型转换和类型强制转换 64 2.6.1 赋值语句中的类型...

    [Visual.C++.2010入门经典(第5版)].Ivor.Horton.part1

    指导读者用C++和C++/Cli设计和创建具体的windows应用程序。 提供了大量可以工作的示例和练习,旨在帮助读者掌握编程技巧。 目录 第1章 使用visual c++ 2010编程 1 1.1 .net framework 1 1.2 clr 2 1.3 编写c++...

    Visual C++ 2005入门经典.part07.rar (整理并添加所有书签)

    19.7.6 链接订单对话框和客户对话框 19.7.7 练习使用数据库查看器 19.8 小结 19.9 练习题 第20章 更新数据源 20.1 更新操作 20.1.1 CRecordset更新操作 20.1.2 事务 20.2 简单的更新示例 20.3 管理更新过程 20.4 向...

    Visual C++ 2005入门经典.part09.rar (整理并添加所有书签)

    19.7.6 链接订单对话框和客户对话框 19.7.7 练习使用数据库查看器 19.8 小结 19.9 练习题 第20章 更新数据源 20.1 更新操作 20.1.1 CRecordset更新操作 20.1.2 事务 20.2 简单的更新示例 20.3 管理更新过程 20.4 向...

    Visual C++ 2005入门经典.part06.rar (整理并添加所有书签)

    19.7.6 链接订单对话框和客户对话框 19.7.7 练习使用数据库查看器 19.8 小结 19.9 练习题 第20章 更新数据源 20.1 更新操作 20.1.1 CRecordset更新操作 20.1.2 事务 20.2 简单的更新示例 20.3 管理更新过程 20.4 向...

    VC++ 控制IE网页操作

    自动监控获取网络资源 以及网页外部链接 内部是全部源码,保证VC6.0可以运行,需要的可以下载下来参考

    C++类的内联成员函数应放在哪

    大部分函数默认是外部链接,而inline函数默认为内部链接。也是说inline函数只能在本文件中使用,对其他文件是不可见的。一般我们使用某个类的时候,都是在文件中加上该类的头文件,以便我们可以使用该类的接口。而...

    理解AndroidBinder机制(二):C++层

    Framework是一个中间层,它对接了底层实现,封装了复杂的内部逻辑,并提供供外部使用的接口。Framework层是应用程序开发的基础。BinderFramework层分为C++和Java两个部分,为了达到功能的复用,中间通过JNI进行衔接...

    数据结构(C++)有关练习题

    d. 当输入一个商品时,能显示该商品是否在库存中,如存在库存中,则显示其名称和数量,否则显示“未找到”。 e. 如有可能,请建立一个存储商品名称和数量的文本文件,并为二叉搜索树建立一个成员函数...

Global site tag (gtag.js) - Google Analytics