多文件程序中的范围
Posted
技术标签:
【中文标题】多文件程序中的范围【英文标题】:scope in multi-file program 【发布时间】:2012-10-18 11:11:17 【问题描述】:我有一个程序,除了 main.cpp 和一个常量头之外,还有两个外部文件。所以总共四个文件。它们包含以下代码:
main.cpp
#include <iostream>
using namespace std;
int ext1_func();
int ext2_func();
int main()
int i;
i = ext1_func();
cout << i << endl;
i = ext2_func();
cout << i << endl;
return 0;
ext1.cpp
#include "const.h"
int asd1=1;
int ext1_func()
return temp_int;
ext2.cpp
#include "const.h"
int asd2 = 2;
int ext2_func()
return temp_int;
const.h
#ifndef CONST_H
#define CONST_H
const int temp_int=1;
#endif
我想要的是:
1) ext1.cpp 中声明的任何变量都应该仅为 ext1.cpp 中的函数所知,对于 ext2.cpp 也是如此。所以“asd1”必须只有“ext1_func”知道,“asd2”才知道“ext2_func”。
2) “exp1.cpp”和“ext2.cpp”中的函数必须能够看到“const.h”中定义的所有值
我相信我编写和附加的代码满足这些要求,但我想问一下我这样做是否正确?有没有比我建议的更简单的方法来获得所需的行为?
提前致谢。
奈尔斯。
【问题讨论】:
所显示代码的最大问题是(1)asdN
变量在其源文件之外可见(在各种答案中扩展讨论),以及(2 ) 没有一个标头声明用于强制使用函数的代码 (main.cpp
) 和定义函数的代码 (extN.cpp
) 之间的一致性。当然,C++ 具有类型安全的链接(与我主要工作的 C 不同)。但是,一般来说,最好不要在源文件中编写 extern 声明——应该有一个头文件来声明用于强制一致性的函数。
【参考方案1】:
在编译单元级别,您在“全局”范围内声明的符号都链接到全局变量空间。
避免这种情况的旧方法是将它们声明为静态。新方法是将它们放入匿名命名空间中。它们也可以在那里声明为静态的。
ext1.cpp
namespace
/*static*/ int asd1=1;
header 中的 const 是可以的,这样声明的常量有特殊的地位,实际上编译器可以在代码中代入值。不过,理想情况下,您至少应该将它们包装在一个(命名的)命名空间中,以避免污染全局命名空间。修改值(使用 const_cast)将是未定义的行为。
如果它是非常量并且您真的想要一个全局的(通常不是一个好主意),您需要在标头中使用 extern 关键字,然后在单个编译单元中创建它的实例。
【讨论】:
关于“标题中的 const 没问题,[...]”,谢谢。我担心以这种方式定义全局常量是一种糟糕的编程风格,现在我将保持原样。 全局常量是可以的,但理想情况下你应该把它们放到一个(命名的)命名空间中,以免“污染”全局命名空间。【参考方案2】:我不会在 main.cpp 中重复 ext1_func()
和 ext2_func()
原型,而是为每个函数定义一个头文件,并在其中添加函数原型:
// ext1.h
#ifndef EXT1_H_INCLUDED
#define EXT1_H_INCLUDED
int ext1_func();
#endif // EXT1_H_INCLUDED
// ext2.h
#ifndef EXT2_H_INCLUDED
#define EXT2_H_INCLUDED
int ext2_func();
#endif // EXT2_H_INCLUDED
在 main.cpp 中:
#include "ext1.h"
#include "ext2.h"
在 ext1.cpp 和 ext2.cpp 中,仅对源文件本地的变量使用匿名命名空间:
// ext1.cpp
#include "const.h"
#include "ext1.h"
namespace
int asd1=1;
// anonymous namespace
int ext1_func()
return temp_int;
与 ext_2.cpp 类似。
您可能还想在头文件中使用方便的 #pragma once
,而不是 #ifndef/#define
包含守卫。
【讨论】:
在“const.cpp”中添加定义而不是在“const.h”中添加定义有什么好处? @niles_1710373:有关是否在标头中定义常量的讨论,请参阅 AndreyT 的 answer。【参考方案3】:您应该将ext1.cpp
和ext2.cpp
中的变量定义为静态,以防止它们被其他文件看到。但是,这是一种非常糟糕的构建方式。相反,您应该将代码分成不同的类。有关详细信息,请参阅this。
【讨论】:
我一般不同意您的观点,即“您应该将代码分成不同的类”。也许应该有类和对象,但 C++ 通常不支持“一切都必须在一个类中”范式。 -1 指向高度抽象的关于 OOP 的 Wikipedia 页面“了解详情”。此外,C++ 无缘无故不支持匿名命名空间之类的东西,而且当前的程序太琐碎,无法保证 OO 设计。【参考方案4】:当您想将变量设置为翻译单元(.cpp
文件)的本地变量时,您可以将它们放入匿名命名空间,如下所示:
namespace
int local_variable = 1;
您也可以使用旧的 C 方式来替代:
static int local_variable = 1;
您也不应该在头文件中定义变量,因为它会在包含此头文件的每个.cpp
模块中重复。您应该在const.h
中将其声明为外部:
extern int external_variable;
然后在对应的const.cpp
文件中定义如下:
int external_variable = 1;
【讨论】:
谢谢!但是可以在“const.h”中定义一个常量变量吗?它还会在每个模块中重复吗? @niles_1710373,对于const int
和其他整数类型都可以。以上是关于多文件程序中的范围的主要内容,如果未能解决你的问题,请参考以下文章