views:

68

answers:

6

After learning more about classes and pointers, I refactored a program I had and wiped out > 200 lines of code, in the process creating two other classes, Location and Piece. The problem is, after getting everything to compile, the linker complains that the constructor for Piece is defined multiple times, with a load of errors:

In function 'Piece':                                         board.o
multiple definition of 'Piece::Piece(int)`                   char_traits.h
In function 'Piece':                                         board.o
multiple definition of 'Piece::Piece(int)`                   piece.cpp
In function 'Piece':                                         player.o
multiple definition of 'Piece::Piece(int)`                   piece.cpp
In function 'Piece':                                         player.o
multiple definition of 'Piece::Piece(int)`                   piece.cpp (yes, same exact error!)
In function 'Piece':                                         refereee.o
multiple definition of 'Piece::Piece(int)`                   char_traits.h
In function 'Piece':                                         referee.o
multiple definition of 'Piece::Piece(int)`                   piece.cpp
...

When I click on the error for char_traits.h, it brings me to this:

static size_t
length(const char_type* __s) //error points here to line 262
{ return __builtin_strlen(__s); }

Another char_traits.h brings me to

  static int
  compare(const char_type* __s1, const char_type* __s2, size_t __n) //line 258, error points here too
  { return __builtin_memcmp(__s1, __s2, __n); }

And just so you know, location.h is the only thing that includes piece.h (well, other files include piece.h indirectly from location including piece.h), board.h is the only thing that includes location.h, and a bunch of classes include board.h

I tried changing the header guard to _OTHELLO_PIECE_H, and tried renaming the class to OPiece (via the IDE). Neither fixed the problem.

The funny thing is, one of the errors has an "in function 'OPiece':", and after that my IDE puts chatter.o, even though neither chatter.h nor chatter.cpp includes anything that includes OPiece.

Any idea what might be causing this redefinition error?

A: 

Hmm... have you made sure you don't have a problem with circular reference?

baflgraf
+1  A: 

The most common cause of a multiple function definition error is putting a function definition in a header file and forgetting to make it inline.

I wouldn't worry much about char_traits.h - this probably means that because of some template runaround, the linker couldn't figure out a better place to claim the definition happened in that particular object file.

aschepler
+1  A: 

You should put the implementation of the constructor in piece.cpp, not directly in piece.h.

sth
A: 

Just a guess: Did you use #include or did you use #import by accident -- which happened to me once :-)

towi
+4  A: 
  1. Rebuild everything
  2. Look for Piece::Piece, and remove all such from header files 2b. Never #include .cpp files
  3. Look for #define that resolves to Piece
Dialecticus
#2 solved it! I accidentally included "piece.cpp" in "location.h". Thanks!
wrongusername
oh wait... still a redifinition error in the compile output, just that qt creator didn't show it in build issues anymore. I think I'll ask a new question instead
wrongusername
+1  A: 

there are two places to implement Piece::Piece(int) in a typical build:

1) the interface (at declaration)

class Piece {
    int d_a;
public:
    Piece(int a) : d_a(a) {
    }
    /* ... */
};

2) in a dedicated cpp file

in Piece.hpp

class Piece {
    int d_a;
public:
    Piece(int a);
    /* ... */
};

in Piece.cpp

Piece::Piece(int a) : d_a(a) {
}

however, templates are defined differently.

the error often indicates that Piece::Piece(int a) : d_a(a) {} is included in multiple cpp files.

each object file produced adds the symbol Piece::Piece(int) where it is visible.

at the end of the build, all objects are merged/linked to create your final binary or executable. then the linker sees that there are copies of this definition and produces an error.

one quick way to diagnose this is (assuming your builds do not take long):

#warning Piece::Piece(int) is visible here
Piece::Piece(int a) : d_a(a) {
}

exactly one warning should be emitted. if more are emitted, then the compiler will likely provide a bit of information (such as the include order).

Justin