Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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++_Sorting_Initialization - Fatal编程技术网

C++ 自定义排序实现会导致链接错误

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; };

我想对一些桥牌数据进行排序,使N(表示无王牌)出现在S(表示黑桃)之后。如果我将所有代码保存在一个文件中,那么下面的代码就可以工作

   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;
}