C++ h文件中的重新定义

C++ h文件中的重新定义,c++,class,redefinition,C++,Class,Redefinition,我解决了两个重新定义的问题,但仍然有一个: 错误2错误LNK2005:“类控制台命令处理程序commandHandler commandHandler”(?commandHandler@@3VConsoleCommandHandler@@A)已在IRC.obj C:\Users\Łukasz\Desktop\IRCClient master\Magic.obj中定义 这是.h文件 魔法 #ifndef Magic_h #define Magic_h #include <iostream&g

我解决了两个重新定义的问题,但仍然有一个:

错误2错误LNK2005:“类控制台命令处理程序commandHandler commandHandler”(?commandHandler@@3VConsoleCommandHandler@@A)已在IRC.obj C:\Users\Łukasz\Desktop\IRCClient master\Magic.obj中定义

这是.h文件

魔法

#ifndef Magic_h
#define Magic_h
#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <map>
#include <algorithm>
#include "src\Thread.h"
#include "src\IRCClient.h"



void signalHandler(int signal);

class ConsoleCommandHandler
{
public:
    bool AddCommand(std::string name, int argCount, void(*handler)(std::string /*params*/, IRCClient* /*client*/));
    void ParseCommand(std::string command, IRCClient* client);
private:
    struct CommandEntry
    {
        int argCount;
        void(*handler)(std::string /*arguments*/, IRCClient* /*client*/);
    };

    std::map<std::string, CommandEntry> _commands;
};

ConsoleCommandHandler commandHandler;

void msgCommand(std::string arguments, IRCClient* client);
void joinCommand(std::string channel, IRCClient* client);
void partCommand(std::string channel, IRCClient* client);


void ctcpCommand(std::string arguments, IRCClient* client);

ThreadReturn inputThread(void* client);

#endif
\ifndef Magic\u h
#定义魔术
#包括
#包括
#包括
#包括
#包括
#包括“src\Thread.h”
#包括“src\IRCClient.h”
无效信号处理器(int信号);
类ConsoleCommandHandler
{
公众:
bool AddCommand(std::string name,int argCount,void(*handler)(std::string/*params*/,IRCClient*/*client*/);
void ParseCommand(std::string命令,IRCClient*client);
私人:
结构命令项
{
int argCount;
void(*handler)(std::string/*arguments*/,irclient*/*client*/);
};
std::map\u命令;
};
控制台命令处理程序命令处理程序;
void msgCommand(std::string参数,IRCClient*client);
void joinCommand(标准::字符串通道,IRCClient*客户端);
void partCommand(标准::字符串通道,IRCClient*客户端);
void ctcpCommand(std::字符串参数,IRCClient*client);
ThreadReturn输入线程(void*客户端);
#恩迪夫
magic.cpp

#include "Magic.h"



void signalHandler(int signal)
{
    volatile bool running;
    running = false;
};


bool ConsoleCommandHandler::AddCommand(std::string name, int argCount, void(*handler)(std::string /*params*/, IRCClient* /*client*/))
    {
        CommandEntry entry;
        entry.argCount = argCount;
        entry.handler = handler;
        std::transform(name.begin(), name.end(), name.begin(), towlower);
        _commands.insert(std::pair<std::string, CommandEntry>(name, entry));
        return true;
    }

void ConsoleCommandHandler::ParseCommand(std::string command, IRCClient* client)
    {
        if (_commands.empty())
        {
            std::cout << "No commands available." << std::endl;
            return;
        }

        if (command[0] == '/')
            command = command.substr(1); // Remove the slash

        std::string name = command.substr(0, command.find(" "));
        std::string args = command.substr(command.find(" ") + 1);
        int argCount = std::count(args.begin(), args.end(), ' ');

        std::transform(name.begin(), name.end(), name.begin(), towlower);

        std::map<std::string, CommandEntry>::const_iterator itr = _commands.find(name);
        if (itr == _commands.end())
        {
            std::cout << "Command not found." << std::endl;
            return;
        }

        if (++argCount < itr->second.argCount)
        {
            std::cout << "Insuficient arguments." << std::endl;
            return;
        }

        (*(itr->second.handler))(args, client);
    }

    struct CommandEntry
    {
        int argCount;
        void(*handler)(std::string /*arguments*/, IRCClient* /*client*/);
    };

    std::map<std::string, CommandEntry> _commands;


void msgCommand(std::string arguments, IRCClient* client)
{
    std::string to = arguments.substr(0, arguments.find(" "));
    std::string text = arguments.substr(arguments.find(" ") + 1);

    std::cout << "To " + to + ": " + text << std::endl;
    client->SendIRC("PRIVMSG " + to + " :" + text);
};

void joinCommand(std::string channel, IRCClient* client)
{
    if (channel[0] != '#')
        channel = "#" + channel;

    client->SendIRC("JOIN " + channel);
}

void partCommand(std::string channel, IRCClient* client)
{
    if (channel[0] != '#')
        channel = "#" + channel;

    client->SendIRC("PART " + channel);
}

void ctcpCommand(std::string arguments, IRCClient* client)
{
    std::string to = arguments.substr(0, arguments.find(" "));
    std::string text = arguments.substr(arguments.find(" ") + 1);

    std::transform(text.begin(), text.end(), text.begin(), towupper);

    client->SendIRC("PRIVMSG " + to + " :\001" + text + "\001");
}

ThreadReturn inputThread(void* client)
{
    std::string command;

    commandHandler.AddCommand("msg", 2, &msgCommand);
    commandHandler.AddCommand("join", 1, &joinCommand);
    commandHandler.AddCommand("part", 1, &partCommand);
    commandHandler.AddCommand("ctcp", 2, &ctcpCommand);

    while (true)
    {
        getline(std::cin, command);
        if (command == "")
            continue;

        if (command[0] == '/')
            commandHandler.ParseCommand(command, (IRCClient*)client);
        else
            ((IRCClient*)client)->SendIRC(command);

        if (command == "quit")
            break;
    }

#ifdef _WIN32
    _endthread();
#else
    pthread_exit(NULL);
#endif
}
#包括“Magic.h”
无效信号处理器(int信号)
{
不稳定bool跑;
运行=错误;
};
bool ConsoleCommandHandler::AddCommand(std::string name,int argCount,void(*handler)(std::string/*params*/,IRCClient*/*client*/)
{
命令输入;
entry.argCount=argCount;
entry.handler=handler;
std::transform(name.begin()、name.end()、name.begin()、towlow);
_insert(std::pair(name,entry));
返回true;
}
void ConsoleCommandHandler::ParseCommand(std::string命令,IRCClient*客户端)
{
if(_commands.empty())
{
std::cout Text==“”)| |(端口盒->文本==“”)| |(用户名盒->文本==“”)| |(频道盒->文本==“”)
{
MessageBox::Show(“Wypełnij wszystkie pola”,“Puste pola”,MessageBoxButtons::OK,MessageBoxIcon::Warning);
服务器盒->焦点();
}
其他的
{
字符串^host\u字符串=服务器\u框->文本;
char*host=(char*)(void*)封送:StringToHGlobalAnsi(主机字符串);
字符串^port\u字符串=端口框->文本;
国际港口;
//字符串^port_String=port.ToString();
字符串^nick\u String=用户名\u框->文本;
std::字符串nick(marshal_as(nick_string));
std::string user=“test”;
irc客户端;
不稳定bool跑;
螺纹;
启动(输入线程和客户端);
if(client.InitSocket())
{
content\u box->Text=“套接字已初始化。正在连接…”+“\r\n”;
if(客户端连接(主机、端口))
{
content\u box->Text=“已连接。登录…”+“\r\n”;
if(客户端登录名(尼克,用户))
{
content\u box->Text=“Logged.”+“\r\n”;
运行=真;
信号(SIGINT,信号处理器);
while(client.Connected()&&running)
client.ReceiveData();
}
if(client.Connected())
client.Disconnect();
content\u box->Text=“已断开连接。”+“\r\n”;
}
}
}
};
};
};
在Magic.h文件中进行以下更改:

extern ConsoleCommandHandler commandHandler;
然后在Magic.cpp文件中添加以下代码:

ConsoleCommandHandler commandHandler;

否则,Magic.obj和IRC.obj都将以
ConsoleCommandHandler commandHandler
结束,因为标头将保留它两次,在每个obj文件中保留一次。

您的问题是什么?请编辑您的问题并将代码简化为MVCE,请参阅
ConsoleCommandHandler commandHandler正在声明一个对象。而且,正如编译器正确指出的那样,当您将此头文件包含到多个源文件中时,您需要重新定义。因此,我必须用它来修复它吗?在头文件中将其声明为
extern
,并在一个源文件中定义它是一种方法。这样做没有帮助:(@titans,我已经更新了我的答案,尝试将
ConsoleCommandHandler commandHandle
声明为
extern
,并将
ConsoleCommandHandler commandHandle
添加到cpp:-)它是有效的,现在我对magic中定义的volitale bool有一个问题。h在magic.cpp中使用,但它在irc.h中显示了它的重新定义,不知道为什么,因为它只在那里使用…@titans,在你为magic提供的源代码中。h我看不到volatile只在magic.cpp文件中使用。顺便说一句,如果你想要线程安全的话,使用std::atomic。
ConsoleCommandHandler commandHandler;