C ++组织实用程序代码,避免“多重定义...”

时间:2013-11-22 19:04:23

标签: c++ g++

我想要一些全局地图,应该在很多地方使用,并且很少使用常用的小功能。以下是我试图组织它的方式。

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'

所以,问题是如何更好地组织这个工具。

2 个答案:

答案 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文件中。