I've an issue and I can't solve it (with google). As practice I write a program about chess. There is a general piece class:
pieces.h :
#ifndef PIECES_H
#define PIECES_H
[...]
class piece{
public:
bool dark; //0 = light, 1 = dark
virtual std::vector<position> sovereign_movement();
types identify; // enum types = {pawn, knight, king, etc...}
position pos;
std::vector<position> horizontal(position a);
std::vector<position> vertical(position a);
std::vector<position> plus90(position a); //basic moves
std::vector<position> minus90(position a);
std::vector<position> Lshape(position a);
piece() : identify(non), pos(position(1,1)) {}
virtual ~piece() {}
};
class Pawn : public piece{
public:
Pawn() { identify = pawn; }
std::vector<position> sovereign_movement() {std::vector<position> sol; return sol;}
~Pawn() = default;
};
[...]
#endif //PIECES_H
And my main for testing:
#include "pieces.h"
int main()
{
piece a;
vector<position> test = a.horizontal();
for(unsigned int i=0; i<test.size() ;i++)
{
cout << test[i].Pconvert() << endl; /// position::Pconvert() just make string
}
return 0;
}
I've a pieces.cpp file what define the longer methods:
#include "pieces.h"
#ifndef PIECES_H
#define PIECES_H
std::vector<position> piece::horizontal(position a){
std::vector<position> sol;
for(int i = 1;i<=8;i++){
sol.push_back(position(i,a.y));
if(i==a.x){sol.pop_back();}
}
return sol;
}
[...]
#endif //PIECES_H
For this I get undefined reference to piece::horizontal(position)
and undefined reference to vtable for piece
for constructor and destructor in header file.
If i do my destructor abstract (virtual ~piece() = 0
) I get:
error: cannot declare variable 'a' to be of abstract type 'piece', because the following functions are pure within 'piece': virtual piece::~piece()
After that I've write default destructors all of derived classes, but writes same. After this I modify my main this way (Pawn
is one of derived classes of piece
):
int main()
{
piece* a = new Pawn();
vector<position> test = a->horizontal(a->pos);
for(unsigned int i=0;i<test.size();i++){
cout << test[i].Pconvert() << endl;
}
return 0;
}
And then I get: undefined reference to 'piece::horizontal(position)'
and undefined reference to piece's destructor in .h, so round is closed.
Could someone help me? Thank you
When you include a header file, the contents of that file replace the #include
line. So when pieces.cpp
starts like this:
#include "pieces.h"
#ifndef PIECES_H
#define PIECES_H
std::vector<position> piece::horizontal(position a){
std::vector<position> sol;
for(int i = 1;i<=8;i++){
sol.push_back(position(i,a.y));
if(i==a.x){sol.pop_back();}
}
return sol;
}
#endif //PIECES_H
it becomes the following after the pre-processor handles the #include
.
#ifndef PIECES_H
#define PIECES_H
class piece{
public:
bool dark; //0 = light, 1 = dark
virtual std::vector<position> sovereign_movement();
types identify; // enum types = {pawn, knight, king, etc...}
position pos;
std::vector<position> horizontal(position a);
std::vector<position> vertical(position a);
std::vector<position> plus90(position a); //basic moves
std::vector<position> minus90(position a);
std::vector<position> Lshape(position a);
piece() : identify(non), pos(position(1,1)) {}
virtual ~piece() {}
};
#endif //PIECES_H
#ifndef PIECES_H
#define PIECES_H
std::vector<position> piece::horizontal(position a){
std::vector<position> sol;
for(int i = 1;i<=8;i++){
sol.push_back(position(i,a.y));
if(i==a.x){sol.pop_back();}
}
return sol;
}
#endif //PIECES_H
Next, account for the PIECES_H
macro. I'll comment out the preprocessing lines as I proceed.
// #ifndef PIECES_H -- PIECES_H is not defined yet, so proceed.
// #define PIECES_H -- now PIECES_H is defined.
class piece{
public:
bool dark; //0 = light, 1 = dark
virtual std::vector<position> sovereign_movement();
types identify; // enum types = {pawn, knight, king, etc...}
position pos;
std::vector<position> horizontal(position a);
std::vector<position> vertical(position a);
std::vector<position> plus90(position a); //basic moves
std::vector<position> minus90(position a);
std::vector<position> Lshape(position a);
piece() : identify(non), pos(position(1,1)) {}
virtual ~piece() {}
};
// #endif //PIECES_H -- end of the earlier #ifndef
// #ifndef PIECES_H -- PIECES_H is still defined from earlier. So skip ahead.
// All these lines are omitted from compilation
// #endif //PIECES_H -- end of the earlier #ifndef
The preprocessor just ripped out the contents of pieces.cpp
because of the mis-use of header guards. Header guards belong in the header (see also A: C++ Header Guard Syntax and Header Placement). Take them out of your source file and it should compile as intended.