C++ 自定义排序实现会导致链接错误
我想对一些桥牌数据进行排序,使N(表示无王牌)出现在S(表示黑桃)之后。如果我将所有代码保存在一个文件中,那么下面的代码就可以工作C++ 自定义排序实现会导致链接错误,c++,sorting,initialization,C++,Sorting,Initialization,我想对一些桥牌数据进行排序,使N(表示无王牌)出现在S(表示黑桃)之后。如果我将所有代码保存在一个文件中,那么下面的代码就可以工作 class Bridge_lt_str : public std::binary_function<std::string, std::string, bool> { public: struct lt_char { const char *tab; };
class Bridge_lt_str : public std::binary_function<std::string, std::string, bool>
{
public:
struct lt_char
{
const char *tab;
};
char tab[CHAR_MAX - CHAR_MIN + 1];
Bridge_lt_str(const std::locale& L = std::locale::classic())
{
const std::ctype<char>& ct = std::use_facet<std::ctype<char> >(L);
for (int i = CHAR_MIN; i <= CHAR_MAX; ++i) // cast for char.
tab[i - CHAR_MIN] = static_cast<char>(i); // (char)i
//Only concerned with ordering C, D, H, S, N=NT.
tab['N' - CHAR_MIN] = tab['Z' - CHAR_MIN];
ct.toupper(tab, tab + CHAR_MAX - CHAR_MIN + 1);
}
};
Bridge_lt_str lt_str;
bool isDenomLess(std::string& lhs, std::string& rhs)
{//NT is the highest denomination. Otherwise, everything sorts normally.
if (lhs[0] == rhs[0]) return lt_str.tab[lhs[1] - CHAR_MIN] < lt_str.tab[rhs[1] - CHAR_MIN];
return lhs[0] < rhs[0];
}
这适用于其他一些排序函数,例如
sort(v_keys.begin(), v_keys.end(), order_by_score_freq);
我在一个单独的头文件中内联了这些函数
inline bool order_by_score_freq(const Result & r1, const Result & r2);
inline bool isDenomLess(std::string& lhs, std::string& rhs);
但是,大概是由于tab数组的初始化,我尝试的任何操作都会导致链接错误
LNK2005: "class Bridge_lt_str lt_str" (?lt_str@@3VBridge_lt_str@@A) already defined in Bridge.obj
非常感谢对合适的include结构的任何帮助 问题在于线路:
Bridge_lt_str lt_str;
改为:
extern Bridge_lt_str lt_str;
然后在其中一个.cpp文件中:
Bridge_lt_str lt_str;
只要定义在类主体内或使用“内联”说明符声明,就可以将代码(在标题中)放在类主体内。您可以将其清理并将其拆分为单独的文件,这从组织的角度来看很有帮助 在您的
.h
头文件中,您尝试并保持专注于规划全局:
class Bridge_lt_str : public std::binary_function<std::string, std::string, bool>
{
public:
struct lt_char
{
const char *tab;
};
Bridge_lt_str(const std::locale& L = std::locale::classic());
char tab[CHAR_MAX - CHAR_MIN + 1];
};
bool isDenomLess(std::string& lhs, std::string& rhs);
如果您不想更改参数,请尝试在参数中标记为const
。isDenomLess
函数不会修改这些字符串,因此const std::string&
是这些参数的合适类型。省略const
通常会传达修改它们的意图。这也会让人烦恼那些试图使用你的函数的人只有一个const
字符串,而你却毫无理由地需要一个非const
的字符串
在其他一些文件中,如main.cpp
中,您可以使用您的类:
int main() {
Bridge_lt_str lt_str;
return 0;
}
您需要链接
main.cpp
(例如main.o
)的编译器输出和另一个编译器输出(例如bridge\u lt\u str.o
)在任何非平凡的C++程序中,这是标准的,所以你应该有一个<代码> Maxfile 或者等同于自动地为你做。< /P>你在头文件中定义了实现吗?这是一个大的“否”。把全局定义移到一个单独的翻译单位,或者标记它们“代码>内联< /代码>。@ TADMAN”这是一个大的“否”。本身并非如此。@user0042如果将非内联
实现放在头文件中,您会问这样的问题。将这些内联
标记是完全不合适的。这不是性能敏感的代码,它可以存在于它应该存在的地方:一个.cpp
实现文件。@tadman编译器(链接器)我会决定是否实际内联该代码。这对我来说没有什么区别。我会将代码放在cpp文件中,如果只是为了避免违反。谢谢-这似乎是一个非常干净的结构。我认为头函数需要删除默认值,即Bridge_lt_str(const std::locale&);但是,一旦完成,它将编译并运行(稍后我将进行测试)。Visual Studio经历了一个阶段,告诉我重新编译的文件已过时,但它似乎已经克服了这一点(我总是怀疑刚刚消失的问题!)如果您使用的是Visual Studio,那么您不必对链接过于操心,因此现在您应该通过清晰地拆分内容,走上正确的道路。默认值可能是正确的,因此我已将其从此处删除。
Bridge_lt_str::Bridge_lt_str(const std::locale& L)
{
const std::ctype<char>& ct = std::use_facet<std::ctype<char> >(L);
for (int i = CHAR_MIN; i <= CHAR_MAX; ++i)
tab[i - CHAR_MIN] = static_cast<char>(i);
//Only concerned with ordering C, D, H, S, N=NT.
tab['N' - CHAR_MIN] = tab['Z' - CHAR_MIN];
ct.toupper(tab, tab + CHAR_MAX - CHAR_MIN + 1);
}
bool isDenomLess(std::string& lhs, std::string& rhs)
{
if (lhs[0] == rhs[0])
return lt_str.tab[lhs[1] - CHAR_MIN] < lt_str.tab[rhs[1] - CHAR_MIN];
return lhs[0] < rhs[0];
}
int main() {
Bridge_lt_str lt_str;
return 0;
}