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中的全局变量、全局函数发生冲突。
相关推荐
### C++内部链接与外部链接详解 #### 一、引言 在C++编程中,了解内部链接与外部链接的概念及其工作原理对于编写高效、可维护的代码至关重要。本文将详细探讨这两个概念,并通过示例帮助读者更好地理解它们在实际...
当我们说“C++中的`const`默认是内部链接”时,这意味着如果我们在全局作用域或者静态存储区定义一个`const`变量,编译器会默认将其链接属性设为内部链接(internal linkage)。这与非`const`全局变量的外部链接...
在C++中,可以使用`FindResource`、`LoadResource`和`LockResource`等函数来访问这些资源。然后,我们可以解析`VS_FIXEDFILEINFO`结构,该结构包含了版本号的详细信息。 接下来,我们将重点放在`...
理解函数内部和外部变量的区别,以及如何使用`static`关键字来改变变量的生命周期,能避免很多困惑。 3. **引用与指针**:两者都可作为别名,但引用必须在定义时初始化且不可改变,而指针可以改变所指向的对象。...
3. **编译和链接**:生成的C++代码需要编译并链接到项目中。确保配置正确,包括链接gSOAP库和其他必要的依赖。 4. **调用WebService**:通过实例化生成的客户端类并调用其成员函数,我们可以发送请求并接收响应。...
2. **作用域与链接性**:C++中的变量和函数有不同的作用域(如局部、全局、类作用域)和链接性(内部、外部)。了解这些规则有助于避免命名冲突和有效地组织代码。 3. **内存管理**:C++提供了对内存的直接控制,...
在C++编程中,动态链接库(DLL)是一种可共享代码和资源的文件格式,它允许多个应用程序同时使用相同的函数和数据。本示例重点讲解如何创建一个C++ DLL并导出类,以及如何在控制台程序中调用这些类的方法。我们将...
### `extern`在C和C++中的作用 #### 前言 在程序设计领域,尤其是在C和C++这两种广泛使用的编程语言中,理解和掌握关键字`extern`的使用方法至关重要。`extern`关键字用于声明一个变量或函数是在当前源文件之外...
- **游戏开发**:由于其性能优势,C/C++ 是游戏引擎和游戏开发中最常用的编程语言之一。 - **高性能计算**:在科学计算、数据分析等领域,C/C++ 提供了极高的性能,用于处理大量数据和复杂的计算任务。 综上所述,C...
2. 封装:封装是隐藏对象内部实现细节的过程,只暴露必要的接口供外部使用。这有助于保护数据,防止未经授权的修改。 3. 继承:继承允许一个类(子类)从另一个类(父类)继承属性和方法。子类可以添加新的特性或...
2. **作用域和链接**:书中深入解析了C++中的作用域规则,包括全局、局部、类作用域以及链接性(内部链接、外部链接)。这些知识对于理解和处理多文件项目至关重要。 3. **类型系统**:C++的类型系统是其强类型语言...
Matlab Engine是一个库,它允许外部应用程序(如C++程序)在运行时启动Matlab会话,并能直接访问Matlab的功能和数据。这种功能使得C++能够调用Simulink模型,执行仿真、数据分析和其他Matlab计算,而无需用户手动...
在《IAR C/C++开发指南》中,有关编译器选项的讨论能够帮助开发者调整和优化编译过程,从而生成更加优化的代码,提升程序的运行效率和稳定性。 整体而言,《IAR C/C++开发指南》是一本为嵌入式开发者量身定制的参考...
外部链接属性适用于所有函数(除了主函数main())和全局变量,允许它们在整个程序的不同部分中被使用。内部链接属性适用于用`static`修饰的函数和全局变量,以及用`const`修饰的符号变量,它们只能在当前转换单元内...
在C++中调用汇编程序主要有两种方法:通过外部链接和内部嵌入。外部链接是将汇编代码编译为静态或动态库,然后在C++代码中通过函数调用来使用。内部嵌入则是将汇编代码直接插入到C++源文件中,作为内联汇编来使用。...
1. **外部链接**:具有外部链接的实体(如全局变量或函数)可以在多个源文件之间共享。如果一个变量或函数在多个文件中定义,但没有声明为static,那么它们在链接阶段必须一致,否则会导致链接错误。 2. **内部链接...
### FLUENT中的C++编程:用户自定义函数(UDF)详解 #### 1.1 什么是UDF? 用户自定义函数(User-Defined Function,简称UDF),是在FLUENT环境中用户自行编写的程序模块,用于扩展FLUENT的基本功能。UDF通过与...
在C++中,`const`默认具有内部链接属性,如果想要让外部文件也能访问,则需要使用`extern`关键字。 #### 四、引用的特性 - **引用的定义**:引用本质上是对已存在变量的别名。它必须在声明时被初始化,并且一旦...