Подтвердить что ты не робот

Уже определено в .obj - нет двойных включений

Мне удалось получить то, что уже определено в ошибке .obj. Это структура моего проекта:

main.cpp

#include "main.h";

main.h

#include <iostream>
#include <string>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include "client.cpp"

client.cpp

#ifndef SOCKET_CLIENT_CLASS
#define SOCKET_CLIENT_CLASS
#ifndef BOOST_ASIO_HPP
#include <boost/asio.hpp>
#endif
/*CLASS DEFINITION HERE*/
#endif

Об этом жалуется компилятор:

main.obj: ошибка LNK2005: "public: bool __thiscall SocketClient:: read (int, char *)" (? read @SocketClient @@QAE_NHPAD @Z) уже в client.obj

Обратите внимание, что он жалуется на мой класс, а не на повышение. Интересно то, что когда я удаляю #include <boost/asio.hpp> из client.cpp, я получаю ошибки, которые вы включаете в main.h тоже.

Как вы можете видеть, я не дважды определяю/включая мой класс, его включал ровно один раз в main.h. Итак, что здесь происходит?
Я прочитал этот ответ, но это не помогло, так как оно предполагает двойные включения. Возьмите этот факт в оглавление перед голосованием за дублирование, потому что это просто означает обезглавить меня без пощады.

4b9b3361

Ответ 1

Это не ошибка компилятора: ошибка возникает из компоновщика. После компиляции компоновщик объединит объектные файлы, полученные в результате компиляции каждого из ваших единиц перевода (.cpp файлов).

Компонент узнает, что у вас есть один и тот же символ, определенный несколько раз в разных единицах перевода, и жалуется на него (это нарушение правила одного определения).

Причина, безусловно, в том, что main.cpp включает client.cpp, и оба эти файла обрабатываются отдельно компилятором для создания двух отдельных объектных файлов. Поэтому все символы, определенные в блоке трансляции client.cpp, будут также определены в блоке перевода main.cpp. Это одна из причин, по которой вы обычно не делаете файлы #include .cpp.

Поместите определение вашего класса в отдельный файл client.hpp, в котором не содержит также определения функций-членов этого класса; то пусть client.cpp и main.cpp включают этот файл (я имею в виду #include). Наконец, оставьте в client.cpp определения функций вашего класса.

client.h

#ifndef SOCKET_CLIENT_CLASS
#define SOCKET_CLIENT_CLASS
#ifndef BOOST_ASIO_HPP
#include <boost/asio.hpp>
#endif

class SocketClient // Or whatever the name is...
{

// ...

    bool read(int, char*); // Or whatever the name is...

//  ...
};

#endif

client.cpp

#include "Client.h"

// ...

bool SocketClient::read(int, char*)
{
    // Implementation  goes here...
}

// ... (add the definitions for all other member functions)

main.h

#include <iostream>
#include <string>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include "client.h"
//              ^^ Notice this!

main.cpp

#include "main.h"

Ответ 2

Вероятно, вы не хотите этого делать:

#include "client.cpp"

Файл A *.cpp будет скомпилирован компилятором как часть вашей сборки. Включив его в другие файлы, он будет скомпилирован снова (и снова!) В каждом файле, в который вы его включаете.

Теперь вот что: вы охраняете его с помощью #ifndef SOCKET_CLIENT_CLASS, однако каждый файл с #include "client.cpp" создается независимо и как таковой найдет SOCKET_CLIENT_CLASS еще не определен. Поэтому содержимое будет включено, а не # ifdef'd.

Если он содержит какие-либо определения вообще (а не просто объявления), то эти определения будут повторяться в каждом файле, в который он был включен.

Ответ 3

Это один из способов преодоления этой проблемы.

  • Просто поставьте прототип в файлы заголовков и включите файлы заголовков в .cpp файлы, как показано ниже. client.cpp

    ifndef SOCKET_CLIENT_CLASS

    определить SOCKET_CLIENT_CLASS

    ifndef BOOST_ASIO_HPP

    включить

    ENDIF

    class SocketClient//Или независимо от имени... {

    //...

    bool read(int, char*); // Or whatever the name is...
    

    //...};

    ENDIF

client.h

bool SocketClient::read(int, char*)
{
    // Implementation  goes here...
}

main.cpp

#include <iostream>
#include <string>
#include <sstream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include "client.h"
//              ^^ Notice this!

main.h

int main()