避免为单个头文件重新定义变量
avoiding redefinition of variables for single header
我对代码有一个单独的头文件要求,这意味着不应该将声明和定义拆分为单独的头文件和源文件。我已经正确地实现了它,并且它按照我的用例的预期工作,其中这个头文件意味着只包含在单个源文件中。
现在,当它在多个源文件中使用时(其中不止一个.cpp包含它),它将失败,并伴随着一些变量被重新声明的链接器错误。这是因为我的代码是-
#ifndef HEADER_HPP
#define HEADER_HPP
....
std::streambuf const *R_coutbuf = std::cout.rdbuf();
std::streambuf const *R_cerrbuf = std::cerr.rdbuf();
std::streambuf const *R_clogbuf = std::clog.rdbuf();
void doSomething(){
[uses if(R_coutbuf) and others]
}
....
#endif HEADER_HPP
现在最好的解决方案是在头文件中声明这些变量,并在单个cpp文件中定义/分配它们,但正如我所说,我希望能够用单个头文件做到这一点。这带来的问题是,如果多个源文件包含它,将会有重新声明。
到目前为止,我不确定我应该如何做到这一点,但我有两个想法-
#ifdef DEFINE_VARIABLES
#define EXTERN /* nothing */
#else
#define EXTERN extern int
#endif /* DEFINE_VARIABLES */
EXTERN global_variable = something;
我不太确定,这能行吗?
我想到的第二种方法是把它放在一个匿名命名空间中,我正在尝试这个,到目前为止它的构建成功了-
#ifndef HEADER_HPP
#define HEADER_HPP
....
namespace R {
namespace {
std::streambuf const *R_coutbuf = std::cout.rdbuf();
std::streambuf const *R_cerrbuf = std::cerr.rdbuf();
std::streambuf const *R_clogbuf = std::clog.rdbuf();
}
void doSomething(){
[uses if(R_coutbuf) and others]
}
}
....
#endif HEADER_HPP
还有其他方法可以实现这个吗?以上两种方法有什么问题吗?
您可以将变量设置为函数中的局部静态变量:
inline std::streambuf const*& R_coutbuf() {
static std::streambuf const* b = std::cout.rdbuf();
return b;
}
宏观技巧我上面描述的方法有什么问题吗?
- 优点
- 在目标文件中产生最小数量的变量。参考匿名命名空间的缺点
- 缺点
- 非常脆弱。当包含头文件时,程序员必须知道是否任何的其他现有源包含变量定义。当源文件数量增加时,这不能很好地扩展
内部链接(匿名命名空间)
- 优点
- 没有宏的缺点。
- 缺点
- 每个包含头文件的对象文件都有自己的变量副本。我不确定,但变量是
const
,并且所有变量在运行时都具有相同的值,链接器可能能够丢弃重复项。在任何情况下,对您的程序来说,差异只是几个字节的值。修改单个变量而不是修改共享变量会改变程序的意义。
- 每个包含头文件的对象文件都有自己的变量副本。我不确定,但变量是
为了比较,让我们考虑单独的源文件选项,你已经排除了。
- 优点
- 在目标文件中产生最小数量的变量,就像宏技巧一样。
- 没有宏的缺点。
- 缺点
- 没有(除非你认为单独的源文件本身就是一个骗局)。
还有其他方法可以实现这个吗?
没有。您可以使用static
关键字来代替匿名命名空间来声明内部链接。
p。如果在头文件中定义任何非模板函数,它们必须声明为内联。您的匿名命名空间示例无法做到这一点。
相关文章:
- 在头文件中定义变量不会出错
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 在命名空间中定义变量
- 是否可以在C++中基于程序集输出(.dll或.exe)定义变量
- 用不同类型重新定义变量
- 具有全局定义变量的递归比没有全局定义变量的递归函数获得更多的堆栈.为什么?(跳入C++)
- 定义变量类型
- 在命名空间中定义变量,但在测试中获取空值
- cmake没有定义变量
- C 中的继承:在亲子类中定义变量
- 在同一函数中定义变量及其静态等效项
- 如何在 Tensorflow C++ 中定义变量的自定义有状态 Op 保存值
- 如何将 int 和 int* 传递到函数中以定义变量
- 在定义变量时调用类函数
- 定义变量与模板
- 定义变量类型
- 为什么您可以在 switch 语句中的"默认"下定义变量,而不能在"case"下定义变量
- C 如何基于另一个变量和某些算术定义变量的值
- C 可以指向具有定义变量的函数
- C 定义变量设置值