Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Already defined in .obj - no double inclusions

I happened to get that already defined in .obj error. This is structure of my project:

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

This is what compiler is complaining about:

main.obj : error LNK2005: "public: bool __thiscall SocketClient::read(int,char *)" (?read@SocketClient@@QAE_NHPAD@Z) already defined in client.obj

Note it is complaining about my class, not boost. One interesting thing is, that when I remove #include <boost/asio.hpp> from client.cpp, I get errors thouhg it is included in main.h too.

As you can see, I'm not double defining/including my class, its included exactly once in main.h. So what's going on here?
I have read this answer, but it was no help, since it expects double inclusions. Take this fact into osideration before voting for duplicate, because this simply means beheading me without mercy.

like image 762
Tomáš Zato - Reinstate Monica Avatar asked Mar 14 '13 22:03

Tomáš Zato - Reinstate Monica


1 Answers

This is not a compiler error: the error is coming from the linker. After compilation, the linker will merge the object files resulting from the compilation of each of your translation units (.cpp files).

The linker finds out that you have the same symbol defined multiple times in different translation units, and complains about it (it is a violation of the One Definition Rule).

The reason is most certainly that main.cpp includes client.cpp, and both these files are individually processed by the compiler to produce two separate object files. Therefore, all the symbols defined in the client.cpp translation unit will be defined also in the main.cpp translation unit. This is one of the reasons why you do not usually #include .cpp files.

Put the definition of your class in a separate client.hpp file which does not contain also the definitions of the member functions of that class; then, let client.cpp and main.cpp include that file (I mean #include). Finally, leave in client.cpp the definitions of your class's member functions.

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"
like image 73
Andy Prowl Avatar answered Sep 23 '22 20:09

Andy Prowl