【问题标题】:Already defined in obj [duplicate]已在 obj 中定义 [重复]
【发布时间】:2019-09-27 03:07:27
【问题描述】:
  1. 错误 LNK2005 "void __cdecl Command::addCommand(struct Command::Command)" (?addCommand@Command@@YAXU11@@Z) 已在 main.cpp.obj D:\Code\cpp\ 中定义discord\DexunBot\MainBot\CMakeLists.txt D:\Code\cpp\discord\DexunBot\MainBot\dexun_client.cpp.obj 1

  2. 错误 LNK2005 "void __cdecl CommandHandler::RegisterCommands(void)" (?RegisterCommands@CommandHandler@@YAXXZ) 已在 main.cpp.obj D:\Code\cpp\discord\DexunBot\MainBot\CMakeLists 中定义.txt D:\Code\cpp\discord\DexunBot\MainBot\dexun_client.cpp.obj 1

  3. 错误 LNK2005 "void __cdecl CommandHandler::CheckExecuteCommand(class DexunClientClass &,struct SleepyDiscord::Message)" (?CheckExecuteCommand@CommandHandler@@YAXAEAVDexunClientClass@@UMessage@SleepyDiscord@@@Z) 已在 main 中定义。 cpp.obj D:\Code\cpp\discord\DexunBot\MainBot\CMakeLists.txt D:\Code\cpp\discord\DexunBot\MainBot\dexun_client.cpp.obj 1

  4. 错误 LNK2005 "class std::unordered_map,class std::allocator >,struct Command::Command,struct std::hash,class std::allocator > >,struct std::equal_to,class std ::allocator > >,class std::allocator,class std::allocator > const ,struct Command::Command> > > Command::all" (?all@Command@@3V?$unordered_map@V?$basic_string@ DU?$char_traits@D@std@@V?$allocator@D@2@@std@@UCommand@3@U?$hash@V?$basic_string@DU?$char_traits@D@std@@V?$ allocator@D@2@@std@@@2@U?$equal_to@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V ?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@UCommand@3@@std@@@2@ @std@@A) 已经定义在 main.cpp.obj D:\Code\cpp\discord\DexunBot\MainBot\CMakeLists.txt D:\Code\cpp\discord\DexunBot\MainBot\dexun_client.cpp.obj 1

在尝试编译我的项目时,我遇到了一些链接器错误。

我已经尝试将我的 command.hpp 也分离到一个 command.cpp 文件中,但我会收到诸如 std::function 不存在或类似的错误。

// command.hpp
class DexunClientClass;

namespace Command {
    using Verb = std::function<
        void(
            DexunClientClass&,
            SleepyDiscord::Message&,
            std::queue<std::string>&
            )
    >;

    struct Command {
        std::string name;
        std::vector<std::string> params;
        std::string description;
        Verb verb;
    };
    using MappedCommands = std::unordered_map<std::string, Command>;
    using MappedCommand = MappedCommands::value_type;
    MappedCommands all;
    void addCommand(Command command) {
        all.emplace(command.name, command);
    }
}

// command_handler.hpp
#include "sleepy_discord/sleepy_discord.h"

#include "commands/help_command.hpp"
#include "dexun_client.hpp"

namespace CommandHandler {
    void RegisterCommands() {
        HelpCommand helpCommand;
        helpCommand.registerHelpCommand();
    }

    void CheckExecuteCommand(DexunClientClass& client, SleepyDiscord::Message message) {
        client.sendMessage(message.channelID, "WFAWFWF");
    }
}

// dexun_client.hpp
#include "sleepy_discord/websocketpp_websocket.h"

class DexunClientClass : public SleepyDiscord::DiscordClient {
public:
    using SleepyDiscord::DiscordClient::DiscordClient;

    void onMessage(SleepyDiscord::Message message) override;
};

// dexun_client.cpp
#include "dexun_client.hpp"

#include "command.hpp"
#include "command_handler.hpp"

std::queue<std::string> split(const std::string& source) {
    std::stringstream ss(source);
    std::string item;
    std::queue<std::string> target;
    while (std::getline(ss, item, ' '))
        if (!item.empty())
            target.push(item);
    return target;
}

void DexunClientClass::onMessage(SleepyDiscord::Message message) {
    if (message.startsWith("dexun") || message.startsWith("dex")) {
        CommandHandler::CheckExecuteCommand(*this, message);

        std::queue<std::string> parameters = split(message.content);
        const std::string mention = "<@" + message.author.ID + ">";
        const std::string mentionNick = "<@!" + message.author.username + ">";
        if (
            //only allow if has more then 1 parameter 
            parameters.size() <= 1 &&
            //only allow if starts with a mention
            (parameters.front() != mention || parameters.front() != mentionNick)
            )
            return;

        //remove the parameters as we go
        parameters.pop();
        if (parameters.empty())
            return;

        //get command
        Command::MappedCommands::iterator foundCommand =
            Command::all.find(parameters.front());
        if (foundCommand == Command::all.end()) {
            sendMessage(message.channelID, "Error: Command not found");
            return;
        }
        parameters.pop();
        if (
            parameters.size() <
            foundCommand->second.params.size()
            ) {
            sendMessage(message.channelID, "Error: Too few parameters");
            return;
        }

        //call command
        foundCommand->second.verb(*this, message, parameters);
    }
}

// main.cpp
#include "dexun_client.hpp"
#include "command_handler.hpp"

int main() {
    DexunClientClass client("token", 2);

    CommandHandler::RegisterCommands();
    std::cout << "Registered Commands" << std::endl;

    client.run();
}```

【问题讨论】:

  • 以强大的ODR 的名义,除非已采取措施防止重复,否则不应在标题中定义。在Command::addCommand的情况下,做吸盘inline
  • 同上 CommandHandler::RegisterCommandsCommandHandler::CheckExecuteCommand,但我怀疑在 cpp 文件中定义它们可能会更好。他们看起来正在做的事情最好不要放在标题中,如果您在开发时更改它们,它们可能会减慢构建速度。
  • 在编译和测试之前考虑少写代码。您可以更快地发现错误,并且不太可能重蹈覆辙。

标签: c++


【解决方案1】:

我注意到的一件事是您没有使用一次标头保护或 pagma。 2、您可以通过包含标准函数库轻松修复“std::function不存在”。

无论如何,当包含 dexun_client.hpp 时,您还将包含 sleepy_discord/websocketpp_websocket。到目前为止没有问题。但是让我们包括 command_handler,它还包括 sleepy_discord/sleepy_discord commands/help_command 和任何包含的内容,以及 dexun_client。我没有看到 dexun_client.hpp 带有任何标头保护或其他方式来阻止它被多次包含。但是这并没有显示为错误,所以我猜测 command.hpp 也包含在 help_command.hpp 中。

另外,我感觉你复制了我的代码,却不知道它是如何工作的。然而,这让我意识到我没有使用任何标题保护,但如果你看看https://github.com/yourWaifu/sleepy-discord/tree/develop/examples/sound-player。不需要,因为它只有一个头文件,而且只包含一次。

Tl 博士:我认为这是因为您缺少头后卫而不是 #pagma 一次。

【讨论】:

  • 我将标头保护排除在代码之外。有头后卫。下次我一定会在我的代码示例中包含它们。我已经放弃了这个项目,因为现在学校太忙了。
猜你喜欢
  • 1970-01-01
  • 2014-11-02
  • 2015-07-27
  • 1970-01-01
  • 2013-02-18
  • 2015-08-10
  • 1970-01-01
  • 2016-11-21
  • 2016-03-09
相关资源
最近更新 更多