c – 乘以定义的符号
如果我在头文件中声明一个全局变量并将其包含在两个.cpp文件中,则链接器会给出一个错误,指出该符号是多重定义的.
我的问题是,为什么这只发生在某些类型的对象(例如int)而不是其他类型(例如enum)? 我使用的测试代码如下: test.h #ifndef TEST_HEADER #define TEST_HEADER namespace test { int i_Test1 = -1; int i_Test2 = -1; }; #endif // TEST_HEADER class1.h #ifndef CLASS_1_HEADER #define CLASS_1_HEADER class class1 { public: void count(); }; #endif //CLASS_1_HEADER class1.cpp #include <iostream> #include "class1.h" #include "test.h" void class1::count() { std::cout << test::i_Test1 << std::endl; } class2.h #ifndef CLASS_2_HEADER #define CLASS_2_HEADER class class2 { public: void count(); }; #endif //CLASS_2_HEADER class2.cpp #include "class2.h" #include <iostream> #include "test.h" void class2::count() { std::cout << test::i_Test2 << std::endl; } main.cpp中 #include "class1.h" #include "class2.h" int main(int argc,char** argv) { class1 c1; class2 c2; c1.count(); c2.count(); return -1; } 构建此代码: g++ main.cpp class1.cpp class2.cpp -o a 产生以下输出:
如果我更改test.h文件,如下所示: test.h(带枚举) #ifndef TEST_HEADER #define TEST_HEADER namespace test { enum val { i_Test1 = 5,i_Test2 }; //int i_Test1 = -1; //int i_Test2 = -1; }; #endif // TEST_HEADER 我没有得到“多重定义”错误,程序给出了所需的输出: 5 6 解决方法
那是因为枚举不是对象 – 它们是类型.如果所有定义都满足一些限制(由所谓的单定义规则(ODR)总结),则可以在整个程序中多次定义类类型(类,结构,联合)和枚举.最重要的两个是
>所有定义都具有相同的标记序列(文本相同) 您的枚举定义满足ODR的所有条件.因此,这是有效的,没有理由让链接器/编译器呻吟(实际上,对于违反ODR,编译器也不需要发出消息 – 大多数都属于所谓的无诊断要求规则,一些违规也会导致未定义的行为). 但是,对于每个非内联函数和对象,这些必须仅定义一次.乘法定义会导致虚假错误,就像您的情况一样.要解决它,只在头文件中放入一个声明(使用“extern”而不使用初始化程序)并将一个定义放入其中一个.cpp文件中(省略“extern”,或者放置初始化程序.如果是const对象,你仍然需要“extern”,因为每个默认的const变量都有内部链接,否则不会导出符号). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |