h文件中的重新定义

redefinition in h files

我解决了几个重定义问题,但还有一个:

错误2 error LNK2005: "class ConsoleCommandHandler commandHandler" (?commandHandler@@3VConsoleCommandHandler@@A) already defined in IRC.obj C:\Users\Łukasz\Desktop\IRCClient-master\Magic.obj

这是 .h 文件

magic.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

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 + " :[=11=]1" + text + "[=11=]1");
}

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
}

irc.h

#pragma once
#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <map>
#include <algorithm>
#include "Magic.h"
#include <msclr/marshal.h>
#include <msclr/marshal_cppstd.h>
#using <mscorlib.dll>


namespace IRCclient {

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using namespace System::IO;
    using namespace System::Runtime::InteropServices;
    using namespace msclr::interop;


    /// <summary>
    /// Summary for MyForm
    /// </summary>


    private: System::Void connect_button_Click(System::Object^  sender, System::EventArgs^  e)
    {
        if ((server_box->Text == "") || (port_box->Text == "") || (username_box->Text == "") || (channel_box->Text == ""))
        {
            MessageBox::Show("Wypełnij wszystkie pola", "Puste pola", MessageBoxButtons::OK, MessageBoxIcon::Warning);
            server_box->Focus();
        }
        else
        {
            String^ host_string = server_box->Text;
            char* host = (char*)(void*)Marshal::StringToHGlobalAnsi(host_string);
            String^ port_string = port_box->Text;
            int port;
            //String^ port_string = port.ToString();
            String^ nick_string = username_box->Text;
            std::string nick(marshal_as<std::string>(nick_string));
            std::string user = "test";


            IRCClient client;
            volatile bool running;
            Thread thread;
            thread.Start(&inputThread, &client);

            if (client.InitSocket())
            {

                content_box->Text = "Socket initialized. Connecting..." + "\r\n";

                if (client.Connect(host, port))
                {
                    content_box->Text = "Connected. Loggin in..." + "\r\n";                 

                    if (client.Login(nick, user))
                    {
                        content_box->Text = "Logged." + "\r\n";                     

                        running = true;
                        signal(SIGINT, signalHandler);

                        while (client.Connected() && running)
                            client.ReceiveData();
                    }

                    if (client.Connected())
                        client.Disconnect();

                    content_box->Text = "Disconnected." + "\r\n";
                }
            }
        }
    };
    };
};

Magic.h 文件中进行以下更改:

extern ConsoleCommandHandler commandHandler;

然后在Magic.cpp文件中添加这段代码:

ConsoleCommandHandler commandHandler;

否则 Magic.obj 和 IRC.obj 都会以 ConsoleCommandHandler commandHandler 结束,因为 header 会保留它两次,每个 obj 文件一次。