提问人:Junyang Liu 提问时间:9/18/2023 更新时间:9/19/2023 访问量:133
在不使用类的情况下在头文件或 cpp 文件中定义私有变量?
Define a private variable in a header file or cpp file without using class?
问:
嗨,我有一个问题,在不使用类的情况下,有没有其他方法可以定义只能在模块内部看到的“私有”变量,这样当我们将不同的模块包含到文件中时,不同模块中具有相同名称的变量就不会冲突?
我知道解决这个问题的最简单方法是使用不同的名称,但我实际上是将 fortran 代码翻译成 C++,除非必要,否则我真的不想更改名称。
我不想使用类的原因是,它实际上是一个大模块,有很多很多变量。在一个类中有这么多私有变量对我来说很奇怪。
谢谢!
我认为头文件中的变量无论如何都是公开的,因为当您将一个头文件包含在另一个文件中时,您实际上将所有内容复制到后面的文件中。基于这个想法,我尝试将那些“应该是私有的”变量从头文件移动到相应的 cpp 文件。但仍然不起作用。
谢谢!
答:
在头文件中使用命名命名空间
假设并包含来自两个 Fortran 模块的名称。module1.h
module2.h
如果这些标头都包含在同一个文件中,则任何重复的名称都将在编译时导致重复的定义错误。.cpp
一个简单的解决方法是将这些名称放在命名命名空间中。
在头文件中,应声明每个名称。这告诉编译器声明不是定义声明。这些将被放置在文件中。extern
.cpp
// module1.h
#ifndef module1_H
#define module1_H
namespace mod1
{
extern double x, y, z;
extern int n;
}
#endif
// module2.h
#ifndef module2_H
#define module2_H
namespace mod2
{
extern double a, b, c;
extern int n;
}
#endif
您还需要在其文件中定义每个名称。在本例中,您可能有 和 。.cpp
module1.cpp
module2.cpp
文件中的定义会导致为先前在头文件中声明的名称分配存储空间。.cpp
extern
// module1.cpp
namespace mod1
{
double x, y, z;
int n;
}
// module2.cpp
namespace mod2
{
double a, b, c;
int n;
}
当其中一个标头包含在文件中时,必须使用作用域解析运算符 (::) 以及命名空间的名称来引用其变量。.cpp
// main.cpp
#include "module1.h"
#include "module2.h"
int main()
{
mod1::n = 0;
mod2::n = 1;
mod2::a = 3.14;
// ...
return 0;
}
在文件中使用匿名命名空间.cpp
如果所需的名称可以放在单独的文件中,并且不需要出现在头文件中,则可以省去命名命名空间。相反,名称应放置在文件的匿名命名空间中。.cpp
.cpp
在匿名命名空间中定义的名称不会导出到链接器。它们具有静态链接,只能在它们首次出现的翻译单元中使用。这可能是 OP 中提到的“私有”变量的最佳近似值。
// module3.cpp
namespace
{
double x, y, z;
int n;
}
void funcA()
{
x = 3.14;
n = 0;
// ...
}
// module4.cpp
namespace
{
double a, b, c;
int n;
}
void funcB()
{
a = 2.7;
n = 1;
// ...
}
使用 C++20 中的模块
C++ 模块可能是处理此问题的最佳方法。除非您明确指定应导出模块中定义的名称,否则不会导出它们。因此,您可以将多个模块导入到同一个翻译单元(即“文件”)中,而不必担心名称冲突。
然而,模块仍然相对较新,并且可能很挑剔。这就是为什么我没有发布使用它们的示例。
评论
static
.cpp