c++中的内部连接与外部连接
Apr 22nd, 2007 by king
一.在学习内部连接与外部连接之前,必须先弄清楚几个概念:
1.声明
一个声明将一个名称引入一个作用域。在c++中,在一个作用域中重复一个声明是合法的。
以下都是声明:
1.声明
一个声明将一个名称引入一个作用域。在c++中,在一个作用域中重复一个声明是合法的。
以下都是声明:
int foo(int,int); //函数前置声明
typedef int Int; //typedef 声明
class bar; //类前置声明
extern int g_var; //外部引用声明
friend test; //友员声明
using std::cout; //名字空间引用声明
在同一作用域中可以多次重复以上声明,但是有两种声明是不能重复的,那就是类成员函数及静态数据成员的声明:
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(); //不可以
};
{
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; //定义一个结构体实例
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)。连接程序把不同编译单元中产生的符号联系起来,构成一个可执行程序。
当一个c或cpp文件在编译时,预处理器首先递归包含头文件,形成一个含有所有 必要信息的单个源文件,这个源文件就是一个编译单元。这个编译单元会被编译成为一个与cpp文件名同名的目标文件(.o或是.obj)。连接程序把不同编译单元中产生的符号联系起来,构成一个可执行程序。
4.自由函数
如果一个函数是自由函数,那么这个函数不是类的成员函数,也不是友元函数。
如果一个函数是自由函数,那么这个函数不是类的成员函数,也不是友元函数。
二.内部连接和外部连接
1.内部连接:如果一个名称对于它的编译单元来说是局部的,并且在连接时不会与其它编译单元中的同样的名称相冲突,那么这个名称有内部连接(注:有时也将声明看作是无连接的,这里我们统一看成是内部连接的)。
以下情况有内部连接:
a)所有的声明
b)名字空间(包括全局名字空间)中的静态自由函数、静态友元函数、静态变量的定义
c)enum定义
d)inline函数定义(包括自由函数和非自由函数)
e)类的定义
1.内部连接:如果一个名称对于它的编译单元来说是局部的,并且在连接时不会与其它编译单元中的同样的名称相冲突,那么这个名称有内部连接(注:有时也将声明看作是无连接的,这里我们统一看成是内部连接的)。
以下情况有内部连接:
a)所有的声明
b)名字空间(包括全局名字空间)中的静态自由函数、静态友元函数、静态变量的定义
c)enum定义
d)inline函数定义(包括自由函数和非自由函数)
e)类的定义
在类中直接定义的函数相当于你写inline,这个叫做隐式内联,但是,不管是显示内联还是隐式内联,都只是给编译器一个请求,最后是否被判断成内联,还得看你的功能模块的复杂度来决定的。故不会发生类重复定义问题。
f)名字空间中const常量定义
g)union的定义
f)名字空间中const常量定义
g)union的定义
2.外部连接:在一个多文件程序中,如果一个名称在连接时可以和其它编译单元交互,那么这个名称就有外部连接。
以下情况有外部连接:
a)类非inline函数总有外部连接,包括类成员函数和类静态成员函数。
b)类静态成员变量总有外部连接。
c)名字空间(包括全局名字空间)中非静态自由函数、非静态友元函数及非静态变量。
以下情况有外部连接:
a)类非inline函数总有外部连接,包括类成员函数和类静态成员函数。
b)类静态成员变量总有外部连接。
c)名字空间(包括全局名字空间)中非静态自由函数、非静态友元函数及非静态变量。
举例说明:
a)声明、enum定义、union定义有内部连接
所有的声明、enum定义及union定义在编译后不会产生连接符号,也就是在不同编译单元中有相同名称的声明及enum、union定义并不会在连接时发生发现多个符号的错误。
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];
};
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;
}
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中的全局变量、全局函数发生冲突。
相关推荐
对内部链接和外部链接的详解,理解下很有用
链接性分为内部链接和外部链接。 外部链接:外部链接的定义可被定义所处的翻译单元(.cpp)内看见,也可以被其他翻译单元引⽤。 具有外部链接性的: · ⾮inline函数。包括命名空间中⾮静态函数、类成员函数和类静态...
输入和输出是通过C++类来实现的,cin和cout是这些类的实例,他们是在C++语言的外部实现。 在C++语言中,有了一种新的注释方法,就是‘//’,在该行//后的所有说明都被编译器认为是注释,这种注释不能换行。C++中...
整理c++const static关键字和内外部链接属性
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 向...
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 向...
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 向...
本书延续了Ivor Horton讲解编程语言的独特方法,从中读者可以学习Visual C++ 2005的基础知识,并全面掌握在MFC和Windows Forms中访问数据源的技术。此外,本书各章后面的习题将有助于读者温故而知新,并尽快成为C++...
《visual c++ 2010入门经典(第5版)》针对visual c++ 2010版本进行了全面更新,介绍了最新的开发环境和如何使用visual c++构建现实世界中的应用程序。拥有本书,您就迈向了通往使用两种c++版本编写应用程序的成功之路...
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 赋值语句中的类型...
指导读者用C++和C++/Cli设计和创建具体的windows应用程序。 提供了大量可以工作的示例和练习,旨在帮助读者掌握编程技巧。 目录 第1章 使用visual c++ 2010编程 1 1.1 .net framework 1 1.2 clr 2 1.3 编写c++...
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 向...
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 向...
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 向...
自动监控获取网络资源 以及网页外部链接 内部是全部源码,保证VC6.0可以运行,需要的可以下载下来参考
大部分函数默认是外部链接,而inline函数默认为内部链接。也是说inline函数只能在本文件中使用,对其他文件是不可见的。一般我们使用某个类的时候,都是在文件中加上该类的头文件,以便我们可以使用该类的接口。而...
Framework是一个中间层,它对接了底层实现,封装了复杂的内部逻辑,并提供供外部使用的接口。Framework层是应用程序开发的基础。BinderFramework层分为C++和Java两个部分,为了达到功能的复用,中间通过JNI进行衔接...
d. 当输入一个商品时,能显示该商品是否在库存中,如存在库存中,则显示其名称和数量,否则显示“未找到”。 e. 如有可能,请建立一个存储商品名称和数量的文本文件,并为二叉搜索树建立一个成员函数...