Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 多定义符号_C++_Compiler Construction - Fatal编程技术网

C++ 多定义符号

C++ 多定义符号,c++,compiler-construction,C++,Compiler Construction,如果在头文件中声明一个全局变量并将其包含在两个.cpp文件中,则链接器会给出一个错误,说明符号是多重定义的。 我的问题是,为什么只对某些类型的对象(例如int)而不对其他类型的对象(例如enum)发生这种情况 我使用的测试代码如下所示: 测试h #ifndef TEST_HEADER #define TEST_HEADER namespace test { int i_Test1 = -1; int i_Test2 = -1; }; #e

如果在头文件中声明一个全局变量并将其包含在两个.cpp文件中,则链接器会给出一个错误,说明符号是多重定义的。 我的问题是,为什么只对某些类型的对象(例如int)而不对其他类型的对象(例如enum)发生这种情况

我使用的测试代码如下所示:

测试h

#ifndef TEST_HEADER
#define TEST_HEADER

namespace test
{           
        int i_Test1 = -1;
        int i_Test2 = -1;
};

#endif // TEST_HEADER
类别1.h

#ifndef CLASS_1_HEADER
#define CLASS_1_HEADER

class class1
{
public:
        void count();
};

#endif //CLASS_1_HEADER
类别1.cpp

#include <iostream>
#include "class1.h"
#include "test.h"

void class1::count()
{
        std::cout << test::i_Test1 << std::endl;
}
类别2.cpp

#include "class2.h"
#include <iostream>
#include "test.h"

void class2::count()
{
        std::cout << test::i_Test2 << std::endl;
}
使用以下内容构建此代码:

g++ main.cpp class1.cpp class2.cpp -o a
生成以下输出:

ld:fatal:symbol
test::i_Test1'是
多重定义:
(文件/var/tmp//ccwWLyrM.o type=OBJT;文件/var/tmp//ccOemftz.o
类型=OBJT);ld:致命:符号
test::i_Test2'是多重定义的: (文件/var/tmp//ccwWLyrM.o type=OBJT;文件/var/tmp//ccOemftz.o 类型=OBJT);ld:fatal:文件处理 错误。未将输出写入到 collect2:ld返回了1个退出状态

如果我更改test.h文件,如下所示:

test.h(带枚举)

我没有得到“乘法定义”错误,程序给出了所需的输出:

5
6

这是因为枚举不是对象,而是类型。类类型(类、结构、联合)和枚举可以在整个程序中多次定义,只要所有定义都满足某些限制(由所谓的一个定义规则(ODR)汇总)。最重要的两个是

  • 所有定义都具有相同的标记序列(文本相同)
  • 使用的名称在所有定义中必须具有相同的含义(解析为相同的事物)。(这是定义上下文的要求)
枚举定义满足ODR的所有条件。因此,这是有效的,并且链接器/编译器没有理由抱怨(实际上,对于违反ODR的情况,编译器也不需要发出消息-大多数消息都属于所谓的无需诊断的规则,一些违反也会导致未定义的行为)

但是,对于每个非内联函数和对象,只能定义一次。用乘法定义这些错误会导致虚假错误,就像您的情况一样。要解决这个问题,只需在头文件中添加一个声明(使用“extern”而不使用初始值设定项),然后在其中一个.cpp文件中添加一个定义(省略“extern”,或者添加一个初始值设定项。如果它是一个const对象,您仍然需要“extern”,因为每个默认常量变量都有内部链接,否则不会导出符号)

g++ main.cpp class1.cpp class2.cpp -o a
#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