C++中namespace跨多个文件的问题

2023-04-08 13:55:54


在C++14标准中(我使用的是最接近的working draft, N3797),在"7.3 Namespaces"中,关于namespace有一句话,“Unlike other declarative regions, the definition of a namespace can be split over several parts of one or more translation units.” 而在"3.3.6 Namespace scope"中的第3条有如下说明:“The outermost declarative region of a translation unit is also a namespace, called the global namespace.” 这说明了平时我们用来说明“全局xxx”的“全局(global)”实际上是namespace的一个例子而已,而每个编译单元(源文件)的最外层的namespace都是global namespace,所以global namespace是天然跨多个文件的,从而了解一般namespace跨文件的行为最好的参照物是就是所谓“全局xxx”的行为——一言以蔽之,基本类似;一般情况下完全可以照搬。

举个例子,比如有如下两个文件:

/* file1.cpp */

#include <iostream>

namespace A
{
	extern int b;
	static int c = 7;
	void print_values();
}

int main()
{
	A::print_values();
}
/* file2.cpp */

#include <iostream>

namespace A 
{
	int b = 3;
	static int c = 50;
	void print_values()
	{
		std::cout<< "c=" << c << "\n";
		std::cout<< "b=" << b << "\n";
	}
}

先考虑一下,先不妨假设没有namespace A的限制,即相关变量和函数都直接定义和声明在全局空间里面,以全局(global)的视角来看这个程序:如print_values()不在file1.cpp中声明时,file1.cpp能编译通过吗?如果file1.cpp中整数b的声明中把extern去掉,链接的时候是不是会报重复定义的错?file2.cpp中的print_values()函数打印的是哪个c的值?

显然对于略有经验的编程者可以很容易的回答上面几个问题。针对有namespace A的情况,只需将这些经验照搬就可以了,简直容易极了。


当然照搬经验是知其然,想要深入了解,知其所以然,还可以参考下面条款:

1. 标准“3.3.1 Declarative regions and scopes”。需要注意,两者的差别是scope的起点是名字的声明,而"Declarative region"是表示程序中引入名字的那个范围(比如一个Block或namespace)。注意potential scope的概念,scope一般情况下与potential scope相等,某些情况下会小一些,小一些的原因是potential scope被挖掉了一块(当前potential scope的某个更内层声明的名字屏蔽了的这个potential scope的同名名字)。

2. 标准“3.3.6 Namespace scope”的说明;

3. 标准“3.7 Storage duration”和"3.7.1 Static storage duration"。这说明了namespace中的变量是静态存储的;

4. 标准“3.5 Program and linkage”,这说明了一般的namespace(有名的)都是external linkage,而匿名namespace是internal linkage的。

  • 作者:oneinmore
  • 原文链接:https://blog.csdn.net/oneinmore/article/details/44941867
    更新时间:2023-04-08 13:55:54