为什么结构声明在C++中违反了 ODR
Why does a struct declaration violate the ODR in C++?
我试图让编译器对一些我认为不违反C++中一个定义规则的代码做出反应。在头文件中,我有两个声明:一个用于结构,一个用于函数,如下所示:
struct TestStruct {
int a;
double d;
};
int k();
然后我故意在另一个带有main((的文件中包含两次头文件,看看会发生什么。
令我惊讶的是,编译器抱怨结构的多个定义。我希望编译器根本不会引发任何多重性错误,因为结构和函数都有纯声明。
只有在我将结构放入标头保护中后,编译器才会停止抱怨。但是,没有为结构分配内存。它不是一个定义。那编译器为什么会生气呢?
不能在单个翻译单元中多次定义结构。
您可以在多个翻译单元中定义它,但定义必须相同。(资料来源:cpp偏好/ODR(。
若要避免此问题,需要在标头中设置包含保护。它将静默地防止标头在每个翻译单元中多次包含。
使用包含保护(或者如果您的编译器可用(编译指示一次。
#ifndef PATH_TO_FILE_FILENAME_H
#define PATH_TO_FILE_FILENAME_H
struct TestStruct {
int a;
double d;
};
int k();
#endif
或者(如果有的话,那就更好了!
#pragma once
struct TestStruct {
int a;
double d;
};
int k();
也可能值得使用命名空间以避免污染全局命名空间
#pragma once
namespace Test
{
struct TestStruct {
int a;
double d;
};
int k();
};
请注意,为了避免 muldefs,如果您决定在标头中提供其定义,您还需要内联声明 k(((如果您需要使用模板而不指定显式模板参数,这有时是不可避免的(。
#pragma once
namespace Test
{
struct TestStruct {
int a;
double d;
};
template<typename T>
inline int k<T>() // This now has to be inline or static.
{
// Some implementation
}
};
编辑:顺便说一句,结构/类的声明和定义之间的区别与函数没有太大区别:
void TestFunction(); // The compiler now knows there's a function called TestFunctionand can attempt to link the symbol information to its implementation somewhere in the compilation unit.
在这种情况下,我们不是在实现函数的实质,只是说它存在,并且由于编译器知道签名(或函数承诺获取和返回的内容(,它可以愉快地继续。在 TestStructs 的情况下,前向声明(不带实现(将是
class TestStruct;
相关文章:
- 这是 basic.def.odr 部分的缺陷吗?
- 为什么显式模板实例化不会破坏 ODR?
- (ODR 使用问题)在不同文件中priority_queue名称相同的结构
- 声明中不一致的no是否违反ODR?
- 是否使用静态 constexpr 变量 odr?
- 使用 -pthread 如何不违反 ODR 规则?
- 为什么编译器不在同一翻译单元中警告 ODR 违规
- C++ standard: ODR and constexpr std::string_view
- ODR 使用的规则不适用于 Visual Studio
- ASAN 检测与动态加载库共享的类的 vtable 的 ODR 违规
- C++模板函数的默认参数的 ODR 规则
- 为什么调用成员函数不调用该对象的 ODR-USE?
- 功能过载和ODR如何共存?(C )
- 为什么结构声明在C++中违反了 ODR
- 是具有预处理前分支实现的结构违反ODR
- 如何在C 中应用ODR(一个定义规则)
- 为什么“静态”功能在不同的tu中不会破坏ODR
- 您可以在类型上使用结构化绑定违反ODR吗?
- 为什么在标题上的结构中声明的模板不违反 ODR 并且专用化会违反 ODR
- GCC 6.3.0 中的 ODR 冲突,类型在两个单独的翻译单元中定义