我想要一些全局地图,应该在很多地方使用,并且很少使用常用的小功能。以下是我试图组织它的方式。
util.h :
#ifndef UTIL_H
#define UTIL_H
#include <unordered_map>
namespace util {
extern std::unordered_map<std::string, short> rgb2short {
{ "000000", 0 },
{ "800000", 1 },
{ "008000", 2 },
{ "808000", 3 },
{ "000080", 4 },
/* ... and so on */
};
short some_util_func() {
/* some util code here */
}
}
#endif
somefile.cpp :
#include "util.h"
/* usage of util::rgb2short and util::some_util_func() */
someotherfile.cpp :
#include "util.h"
/* usage of util::rgb2short and util::some_util_func() */
编译器没有接受并回复了许多multiple definition of 'util::rgb2short'
等
所以,问题是如何更好地组织这个工具。
答案 0 :(得分:3)
至少在数据方面,标题应该只包含声明。该声明必须包含extern
关键字和(您错误的部分)必须不包含初始值设定项。
唯一的例外(它根本不是常见的)是你想要为包含标题的每个翻译单元单独复制数据。在这种非常具体的情况下,您需要指定数据为static
而不是extern
。
在您的情况下,util.h
应仅包含rgb2short
的外部声明。定义(包括初始化程序)应该在某个.cpp
文件中(例如,util.cpp
)。同样,util.h不应包含some_util_func()
的定义。它应该只包含一个声明,并且(再次)放在源文件中的定义,例如util.cpp
。
所以,util.h最终看起来像这样:
#ifndef UTIL_H
#define UTIL_H
#include <unordered_map>
namespace util {
extern std::unordered_map<std::string, short> rgb2short;
short some_util_func();
}
#endif
Util.cpp看起来像这样:
#include "util.h"
namespace util {
std::unordered_map<std::string, short> rgb2short {
{ "000000", 0 },
{ "800000", 1 },
{ "008000", 2 },
{ "808000", 3 },
{ "000080", 4 },
/* ... and so on */
};
short some_util_func() {
/* some util code here */
}
}
然后你就像你已经完成#include "util.h"
一样,还可以将util.obj
(或util.o,或任何目标文件命名)链接到其他目标文件。
答案 1 :(得分:1)
您应该将声明放在标题中,将定义放在源文件中,如下所示:
<强> util.h 强>
#ifndef UTIL_H
#define UTIL_H
#include <unordered_map>
namespace util {
extern std::unordered_map<std::string, short> rgb2short;
}
#endif
并在 util.cpp :
#include "util.h"
namespace util {
std::unordered_map<std::string, short> rgb2short {
{ "000000", 0 },
{ "800000", 1 },
{ "008000", 2 },
{ "808000", 3 },
{ "000080", 4 },
/* ... and so on */
};
}
这将避免这些错误。对于该函数,要么将其标记为inline
并将代码放在标题中,要么只将标记放在标题中(不需要extern
)并将正文放入CPP文件中。