文章

命名空间重定义问题

1.起因

在命名空间里面定义了一些变量,但是编译不过,说是有重定义问题

代码是这样的,在另外两个cpp文件里用到了这个头文件,造成了这个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// a.h
namespace LinesInfoFunc
{
    void func1();
    void func2();
	std::vector<OdDbMTextFragment> vecOdDbTextFrag;
	std::vector<CString> vLineStr;
	std::map<int, CString> mParagraph;
	std::map<int, CString> mLineSpacing;
};

// b.cpp
#include "a.h"

// c.cpp
#include "a.h"

2.解决方法

在声明变量时加上extern,同时在cpp里面实现定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// a.h
namespace LinesInfoFunc
{
    void func1();
    void func2();
	extern std::vector<OdDbMTextFragment> vecOdDbTextFrag;
    extern std::vector<CString> vLineStr;
    extern std::map<int, CString> mParagraph;
    extern std::map<int, CString> mLineSpacing;
};

// a.cpp
namespace LinesInfoFunc
{
	std::vector<OdDbMTextFragment> vecOdDbTextFrag;
	std::vector<CString> vLineStr;
	std::map<int, CString> mParagraph;
	std::map<int, CString> mLineSpacing;
};

3.问题分析

命名空间只不过是为了不让名字重复,而在两个cpp里面都调用了头文件,相当于这些变量被定义了两次,就类似于你是这样写的

1
2
std::vector<int> sss;
std::vector<int> sss;

这样就会报重定义错

直接用最开始的代码写,就相当于声明并定义,虽然你并没有定义,但是会自动初始化的。

而加完extern就是只声明不定义,这样其他cpp引用了头文件,就不会有重定义的情况。

网上看到的: extern关键字用来声明变量,或者函数名以及对象名在其他文件中已经定义过,它通常只是起到一个说明的作用,只是告诉编译器这个变量来自其他文件,编译器会根据这个它提供的变量和名字在其他文件中查找

可以看这个链接每日一问3: C++中extern关键字的作用

里面提到:

在介绍extern之前,我们需要了解一下变量的声明和定义。变量的声明指向程序表名变量的类型和名字,即使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。而变量的定义指申请存储空间,并将其与变量名相关联,除此之外,还可以为变量指定初始值。在程序中变量可以声明多次,但只能定义一次。一般而言,定义就是声明。但C++中由于extern的缘故,变量的声明和定义是可以分开的。凡是没有带extern的声明同时也都是定义

本文由作者按照 CC BY 4.0 进行授权