Ya definido en .obj – sin inclusiones dobles

5 minutos de lectura

avatar de usuario
Tomáš Zato – Reincorporar a Mónica

Obtuve eso ya definido en .obj error. Esta es la estructura de mi proyecto:

principal.cpp

#include "main.h";

principal.h

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

cliente.cpp

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

Esto es de lo que se queja el compilador:

main.obj: error LNK2005: “público: bool __thiscall ClienteSocket::leer(int,char *)” ([email protected]@@[email protected]) Ya definido en cliente.obj

Tenga en cuenta que se queja de mi clase, no de impulso. Una cosa interesante es que cuando elimino #include <boost/asio.hpp> de cliente.cpprecibo errores también está incluido en main.h.

Como puede ver, no estoy definiendo/incluyendo dos veces mi clase, está incluida Exactamente una vez en principal.h. Entonces, ¿qué está pasando aquí?
He leído esta respuesta, pero no fue de ayuda, ya que espera inclusiones dobles. Toma este hecho en consideración antes de votar por el duplicado, porque esto simplemente significa decapitarme sin piedad.

  • no incluir .cpp archivos, incluir .h archivos en cambio, si no tienes uno, haz uno, aparte de eso, no hay suficiente información aquí para decir más.

    – Serdalis

    14/03/2013 a las 22:19

  • Entonces, ¿ha compilado client.cpp una vez solo y una vez incluido en main.cpp?

    – Bo Person

    14/03/2013 a las 22:23

avatar de usuario
Andy merodea

Esto no es una compilador error: el error proviene del enlazador. Después de la compilación, el enlazador fusionará los archivos de objetos resultantes de la compilación de cada una de sus unidades de traducción (.cpp archivos).

El enlazador descubre que tiene el mismo símbolo definido varias veces en diferentes unidades de traducción y se queja de ello (es una violación de la regla de definición única).

La razón es sin duda que main.cpp incluye client.cppy ambos archivos son procesados ​​individualmente por el compilador para producir dos archivos de objetos separados. Por lo tanto, todos los símbolos definidos en el client.cpp unidad de traducción se definirá también en el main.cpp unidad de traducción. Esta es una de las razones por las que no sueles #include .cpp archivos

Ponga la definición de su clase en un aparte client.hpp archivo que hace no contener también las definiciones de las funciones miembro de esa clase; entonces, deja client.cpp y main.cpp incluir ese archivo (quiero decir #include). Finalmente, deja en client.cpp las definiciones de las funciones miembro de su clase.

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

cliente.cpp

#include "Client.h"

// ...

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

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

principal.h

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

principal.cpp

#include "main.h"

  • Alguna idea de qué hacer, si cambia el nombre client.cpp a client.h ¿no ayudó? También he movido la definición de clase a client.hpp

    – Tomáš Zato – Reincorporar a Mónica

    14/03/2013 a las 22:31

  • @TomášZato No puede simplemente cambiar el nombre del archivo, ¿para qué serviría eso? #include no importa el nombre que le des a tus archivos, es el contenido Eso importa.

    – J Bentley

    14/03/2013 a las 22:32

  • @TomášZato Consulte esta respuesta para obtener una explicación sobre cómo separar su código en archivos .cpp y .h correctamente.

    – J Bentley

    14/03/2013 a las 22:34

  • ¿Cuál es el punto de #include "client.h" en el interior client.cpp? Además, ¿puede ajustar su ejemplo para incluir cómo se declararían y definirían funciones libres (funciones que no pertenecen a la clase)?

    – Minh Tran

    12 de marzo a las 17:45

Probablemente no quieras hacer esto:

#include "client.cpp"

El compilador habrá compilado un archivo *.cpp como parte de su compilación. Al incluirlo en otros archivos, se compilará nuevamente (¡y otra vez!) en cada archivo en el que lo incluya.

Ahora aquí está la cosa: Lo estás protegiendo con #ifndef SOCKET_CLIENT_CLASSsin embargo, cada archivo que tiene #include "client.cpp" se construye de forma independiente y como tal encontrará SOCKET_CLIENT_CLASS aún no definido. Por lo tanto, se incluirán sus contenidos, no #ifdef’d out.

Si contiene alguna definición (en lugar de solo declaraciones), estas definiciones se repetirán en cada archivo donde se incluya.

Recomiendo hacerlo en 2 rellenos (.h .cpp) Pero si eres perezoso solo agrega inline antes de la función Entonces se verá algo como esto

inline void functionX() 
{ }

más sobre funciones en línea:

Las funciones en línea son una función de mejora de C++ para aumentar el tiempo de ejecución de un programa. Las funciones se pueden instruir al compilador para que las haga en línea para que el compilador pueda reemplazar la definición de la función donde sea que se llame. El compilador reemplaza la definición de funciones en línea en tiempo de compilación en lugar de referirse a la definición de función en tiempo de ejecución. NOTA: esta es solo una sugerencia para que el compilador haga la función en línea, si la función es grande (en términos de instrucciones ejecutables, etc.), el compilador puede ignorar la solicitud “en línea” y tratar la función como una función normal.

más información aquí

  • En caso de que tenga que incluir un archivo .cpp, esta sería una buena idea.

    – Hadi GhahremanNezhad

    12 oct 2020 a las 17:45

¿Ha sido útil esta solución?