C++编译单元和命名空间

编译单元

编译单元,指的是代码的物理组织形式。根据C++标准,每一个cpp 文件就是一个编译单元。

  • 编译器不会去编译 `.h` 或者 `.hpp` 文件;
  • 编译器只会编译 `.c` 或 `.cpp` 文件;

简单来说,当一个c或cpp文件在编译时,预处理器首先递归包含头文件,这也就是为什么常会有:#ifndef……#define……#endif。之后,形成一个含有所有必要信息的单个源文件,这个源文件就是一个编译单元。这个编译单元会被编译成为一个与cpp文件名同名的目标文件

编译器不能检查跨越目标文件或编译单元之间的名称冲突,这是链接器的工作。链接器把不同编译单元中产生的符号联系起来,构成一个可执行程序。如:

//文件first.cpp
int integerValue = 0;
int main(){
	int integerValue = 0;
	return 0;
};
//文件second.cpp
nt integerValue = 0;
/* 错误: error LNK2005: "int integerValue" ([email protected]@3HA) 已经在 second.obj 中定义	first.obj	*/

GCC将C++代码转为机器码,理论上需要四个步骤:预处理(preprocessing)、编译(compilation)、汇编(assembly)以及链接(linking)3;四个步骤对应四个主体:预处理器(preprocessor)、编译器(compiler)、汇编器(assembler)以及链接器(linker)。实际预处理与编译其实是一个步骤,共需要三个步骤:预处理&编译、汇编以及链接。参见:GCC的C++入门。

宏include的作用

C/C++中的宏本质是文本处理器,`#include` 从机制上来说,只是一种内容的拷贝。参见:深入理解include预编译原理

作用域

作用域指的是对象(变量、类or函数)的可见性。作用域有:类内部,代码块内部,函数内部等等。函数外部声明和定义的变量的作用域为整个文件,从定义处到本文件末尾。如果函数内部局部变量和外部的全局变量重名,此时在函数内操作外部全局变量时就要使用作用域操作符 `::` 符号。 如:

int integerValue = 0; //全局变量
int main(){
int integerValue = 0;
::integerValue=10;  //切换到全局作用域
return 0;
};

链接性

名称链接性分为内部(internal)和外部(external),指的是:名称在一个还是多个编译单元中可用。const变量默认链接性为内部,如果要修改需要显示的声明进行覆盖。

命名空间

命名空间基本思想是,将相关的项目组合到一个特定的(已命名区域)。关键字namespace,用法类似结构体和类:namespace 名称{} 。对于已命名的命名空间,可以有多个实例。这些实例可以在一个文件中,也可在不同的编译单元,编译器会把它们合并成一个命名空间。

命名空间可以嵌套,因为命名空间的定义也是声明,如:

namespace Window{
	namespace Pane{
		int a;
	}
}
// 在命名空间外部访问就是:
Window::Pane::a;

命名空间中可以声明和定义函数,但是优秀的设计一般将接口(声明)和实现(定义)分开,所以命名空间定义中一般只放声明。详见Google C++ Style Guide 。添加新成员,只能在命名空间体体内进行。

命名空间使用,using关键字导入后,作用域从声明处到当前作用域结束:

  • using编译:将命名空间中声明的所有名称导入当前作用域。 如:using namespace std;
  • using声明:将命名空间中声明的指定名称导入到当前作用。如 :using std::cout;

命名空间可以起别名,尤其对于命名空间名字很长时适用,注意不要和已有的命名空间冲突。未命名命名空间,常用于防止目标文件和其他编译单元中的全局数据发生名称冲突。每个编译单元都有一个独一无二的未命名名称空间。

C++编译单元和命名空间

时间: 2024-08-10 02:09:43

C++编译单元和命名空间的相关文章

转:不同编译单元内定义的non-local static 对象的初始化顺序

<Effective C++>条款4中提到了”留意不同编译单元内的non-static变量的初始化顺序“ 下文的描述得很详细,转载过来了. http://blog.csdn.net/chgaowei/article/details/6001433 static对象包括global对象,定义于namespace作用域的对象,在class内的对象,在函数内,以及file作用域内被声明为static的对象. local-static 对象指的是定义在函数内部的对象.其他的被称为non-local-s

此编译单元不包含在frame元数据中指定的factoryClass,无法加载配置的运行时共享库

警告:此编译单元不包含在frame元数据中指定的factoryClass,无法加载配置的运行时共享库.要在没有运行时共享库的情况下进行编译,请将 -static-link-runtime-shared-libraries  选项设置为true, 或删除 -runtime-shared-libraries 选项. 通过修改FlashBuilder4\Adobe Flash Builder 4\sdks\4.0.0\frameworks  下的flex-config.xml,将 <static-li

C#6.0语言规范(九) 命名空间

C#程序使用命名空间进行组织.命名空间既可以用作程序的“内部”组织系统,也可以用作“外部”组织系统 - 一种呈现暴露给其他程序的程序元素的方式. 提供了使用指令(使用指令)以便于使用命名空间. 编译单位 compilation_unit定义了源文件的总体结构.编译单元由零个或多个using_directive组成,后跟零个或多个global_attributes,后跟零个或多个namespace_member_declaration. 1 compilation_unit 2 : extern_

C#习题大全

C#习题大全 1.String str=new String("a")和String str = "a"有什么区别? String str = "a"; 这个只是一个引用,内存中如果有“a"的话,str就指向它,如果没有才创建如后还用到"a"这个字符串的话并且是这样用: String str1 = "a"; String str2 = "a"; String str2 = &q

asp.net c# 网上搜集面试题目大全(附答案)

1.String str=new String("a")和String str = "a"有什么区别? String str = "a"; 这个只是一个引用,内存中如果有“a"的话,str就指向它,如果没有才创建如后还用到"a"这个字符串的话并且是这样用: String str1 = "a"; String str2 = "a"; String str2 = "a&q

C#6.0语言规范(三) 基本概念

应用程序启动 具有入口点的程序集称为应用程序.运行应用程序时,会创建一个新的应用程序域.应用程序的几个不同实例可以同时存在于同一台机器上,并且每个实例都有自己的应用程序域. 应用程序域通过充当应用程序状态的容器来启用应用程序隔离.应用程序域充当应用程序中定义的类型及其使用的类库的容器和边界.加载到一个应用程序域中的类型与加载到另一个应用程序域中的相同类型不同,并且应用程序域之间不直接共享对象实例.例如,每个应用程序域都有自己的这些类型的静态变量副本,每个应用程序域最多运行一次类型的静态构造函数.

C#6.0语言规范(十) 类

类是可以包含数据成员(常量和字段),函数成员(方法,属性,事件,索引器,运算符,实例构造函数,析构函数和静态构造函数)和嵌套类型的数据结构.类类型支持继承,这是一种派生类可以扩展和专门化基类的机制. 类声明 一个class_declaration是type_declaration(类型声明,声明一个新的类). 1 class_declaration 2 : attributes? class_modifier* 'partial'? 'class' identifier type_paramet

程序集=命名空间

命名空间是用来组织和重用代码的编译单元.如同名字一样的意思,NameSpace(名字空间),之所以出来这样一个东西,是因为人类可用的单词数太少,并且不同的人写的程序不可能所有的变量都没有重名现象,对于库来说,这个问题尤其严重,如果两个人写的库文件中出现同名的变量或函数(不可避免),使用起来就有问题了,为了解决这个问题,引入了名字空间这个概念,通过使用 namespace xxx;你所使用的库函数或变量就是在该名字空间中定义的,这样一来就不会引起不必要的冲突了. 所谓namespace,是指标识符

转:C++中命名空间污染注意点 blog.sina.com.cn/s/blog_af68a2c201015pqo.html

一. 为什么需要命名空间(问题提出) 命名空间是ANSIC++引入的可以由用户命名的作用域,用来处理程序中 常见的同名冲突. 在 C语言中定义了3个层次的作用域,即文件(编译单元).函数和复合语句.C++又引入了类作用域,类是出现在文件内的.在不同的作用域中可以定义相同名字的变量,互不于扰,系统能够区别它们. 1.全局变量的作用域是整个程序,在同一作用域中不应有两个或多个同名的实体(enuty),包括变量.函数和类等. 例:如果在文件中定义了两个类,在这两个类中可以有同名的函数.在引用时,为了区