Understanding classes: broken code

Hello,

I'm trying to make a program inspired from the chess game to develop a working understanding of classes interaction, inheritance, etc..
The way I want it to work is:
-board class, that is basically a class piece pointer matrix. if a piece exists in the square, map[x][y] = &piece; else map[x][y] = NULL;
-piece class, that knows it's own coordinates and where it wants to go.

The problem is at class pion::move (lines 69 -- 81),I get this sort of errors: "sah_minimal.cpp:71:16: error: invalid use of incomplete type 'struct board'" Defining piece and pion after the board class definition would be useless because I have a circular dependency.

Any help or suggestion would be apreciated.

Andrei.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <iostream>
using namespace std;

class board;

class piece
{
	char a;
	int x, y;
	board* pboard;
	
	public:
		
	piece()
	{
		a = 'x';
		x = 0;
		y = 0;
	};
	
	bool seta ( const char b)
	{
		a = b;
		//~ cout << "\n seta() set value";
		return true;
	};
	
	bool setxy ( int a, int b)
	{
		x = a;
		y = b;
		cout << "\n piece.setxy() ";
		return true;
	};
	
	bool setpboard ( board& a)
	{
		pboard = &a;
		//~ cout << "\n bound to board "<<pboard;
		return true;
	};
	
	char geta ()
	{
		//~ cout <<"\n geta() returning "<<a;
		return a;
		
	};
	friend class pion;
};

class pion: public piece
{
	//~ char a; -- this works?!?!
	
	public:
	
	pion()
	{
		//~ a = 'p'; --- this doesn't work because a is primitive:private ???
		seta('p');
		//~ cout << "\n pion() "<<a;
	};
	
	~pion()
	{ };
	
	bool move ()
	{
			
		if ( pboard[x][y+1] == NULL )
		//~ {
			//~ cout << "\n move() moving pawn ";
			//~ pboard [x][y+1] = this;
			//~ y = y+1;
			//~ pboard [x][y] = NULL;
		//~ }
		//~ else
			//~ cout << "\n move() illegal move ";
		return true;
	};
	;
	
};
	

class board
{
	piece * map[8][8];
	public:
	
	board ()
	{
		cout << "\n making tabla";
		int i, j;
		//~ cout <<endl;
		for ( j = 0; j<=7; j++)
		{
			for ( i = 0; i<=7; i++)
			{
				map[i][j] = NULL;
			//~ cout << " " << board [i][j];
			}
		//~ cout << endl;
		}
	};
	
	~board()
	{
		cout << "\n destroying tabla";
	};
	
	void addpiece ( int x, int y, piece &p)
	{
		map [x%7][y%7] = &p;
		p.setxy(x%7,y%7);
		p.setpboard(*this);
	};

	void print ()
	{
		//~ cout << "\n this board is "<<&map;
		int i, j;
		cout <<"\n tabla este "<<endl;
		for ( j = 0; j<=7; j++)
		{
			for ( i = 0; i<=7; i++)
			{
				if ( map [i][j] != NULL ) cout <<  (*map [i][j] ).geta();
				else
					cout << "_";
			}
		cout << endl;
		}
		cout << endl;
	};
	

	
	friend class piece;
	//~ friend class pion;
};



int main ()
{
	piece surub;
	pion pio;
	//~ surub.a = 3;
	board board1;
	board1.print();
	board1.addpiece( 1,0,surub);
	board1.addpiece ( 1,1,pio);
	board1.print();
	

}

You need to separate the class definition from the function bodies. Typically this is done by putting classes in headers and the function bodies in separate cpp files.

See section 4 of this article for some guidelines:
http://cplusplus.com/forum/articles/10627/#msg49679


Specifically, in pion, the body of the functions that use board must come after the board definition. This an easily be accomplished like so.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// pion.h

#include "piece.h"

class pion: public piece
{
	//~ char a; -- this works?!?!
	
	public:
	
	pion();
	
//	~pion();  (no need for a dtor if it's empty)
	
	bool move ();
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// pion.cpp

#include "pion.h"
#include "board.h"  // now board is fully defined

pion::pion()
{
  // body goes here
}

bool pion::move()
{
  // body goes here.  Now you can use board and it's fine
}
Hello,

Thank you for your reply, Disch.
I've read your article and several more on the subject of header files. However I still can't get my code to run; please help me solve it.

I'm almost sure that the trouble is with the way the includes are done, but i've had no success with different ways of include ( eg. in sah_class_piece.cpp include sah_class_board.h and sah_class_piece.h and in main include only sah_class_piece.cpp).
With the following layout, I get "undefined reference" to almost all class member functions.

sah_class_board.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef SAH_CLASS_BOARD_H
#define SAH_CLASS_BOARD_H

class piece;

class board
{
	piece * map[8][8];
	public:
	
	board ();

	
	~board();

	
	void addpiece ( int , int , piece &);

	void print ();

	

	
	//~ friend class piece;
	//~ friend class pion;
};

#endif 


sah_class_board.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include "sah_class_board.h"

using namespace std;


	board::board ()
	{
		cout << "\n making tabla";
		int i, j;
		//~ cout <<endl;
		for ( j = 0; j<=7; j++)
		{
			for ( i = 0; i<=7; i++)
			{
				map[i][j] = NULL;
			//~ cout << " " << board [i][j];
			}
		//~ cout << endl;
		}
	};
	
	board::~board()
	{
		cout << "\n destroying tabla";
	};
	
	void board::addpiece ( int x, int y, piece &p)
	{
		map [x%7][y%7] = &p;
		p.setxy(x%7,y%7);
		p.setpboard(*this);
	};

	void board::print ()
	{
		//~ cout << "\n this board is "<<&map;
		int i, j;
		cout <<"\n tabla este "<<endl;
		for ( j = 0; j<=7; j++)
		{
			for ( i = 0; i<=7; i++)
			{
				if ( map [i][j] != NULL ) cout <<  (*map [i][j] ).geta();
				else
					cout << "_";
			}
		cout << endl;
		}
		cout << endl;
	};


sah_class_pieces.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef SAH_CLASS_PIECES_H
#define SAH_CLASS_PIECES_H

class board;

class piece
{
	char a;
	int x, y;
	board* pboard;
	
	public:
		
	piece();
	
	bool seta ( const char );
	
	bool setxy ( int , int );
	
	bool setpboard ( board& );
	
	char geta ();
	
};

class pion: public piece
{
	
	public:
	
	pion();
	
	~pion();
	
	bool move ();
	
	
};


#endif 


sah_class_pieces.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include "sah_class_pieces.h"
		
	piece::piece()
	{
		a = 'x';
		x = 0;
		y = 0;
	};
	
	bool piece::seta ( const char b)
	{
		a = b;
		//~ cout << "\n seta() set value";
		return true;
	};
	
	bool piece::setxy ( int a, int b)
	{
		x = a;
		y = b;
		cout << "\n piece.setxy() ";
		return true;
	};
	
	bool piece::setpboard ( board& a)
	{
		pboard = &a;
		//~ cout << "\n bound to board "<<pboard;
		return true;
	};
	
	char piece::geta ()
	{
		//~ cout <<"\n geta() returning "<<a;
		return a;
		
	};



	
	pion::pion()
	{
		//~ a = 'p'; --- this doesn't work because a is primitive:private ???
		seta('p');
		//~ cout << "\n pion() "<<a;
	};
	
	pion::~pion()
	{ };
	
	bool pion::move ()
	{
			
		//~ if ( pboard[x][y+1] == NULL )
		//~ {
			//~ cout << "\n move() moving pawn ";
			//~ pboard [x][y+1] = this;
			//~ y = y+1;
			//~ pboard [x][y] = NULL;
		//~ }
		//~ else
			//~ cout << "\n move() illegal move ";
		return true;
	};


sah_minimal_include.cpp :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include "sah_class_board.h"
#include "sah_class_pieces.h"
using namespace std;




int main ()
{
	piece surub;
	pion pio;
	//~ surub.a = 3;
	board board1;
	board1.print();
	board1.addpiece( 1,0,surub);
	board1.addpiece ( 1,1,pio);
	board1.print();
	

}

sah_class_board.cpp need to #include sah_class_pieces.h because it is using the piece class.

sah_class_pieces.cpp might have to #include sah_class_board.h ... but I'm not sure. It doesn't look like Piece is dereferencing board anywhere so maybe it's not necessary.
The code is working provided I included booth headers in all cpps, and the circular dependency is functional.
The problem was that I didn't compile the files properly (the IDE was trying to compile them separately).
Corect compilation and execution is:

$g++ -c *.cpp
$g++ -o a.out *.o
$./a.out

I can't thank you enough, Disch, I wouldn't have trusted my code enough to look to problems elsewhere whitout your guidance.

Corect compilation and execution is:

$g++ -c *.cpp
$g++ -o a.out *.o
$./a.out


Or you could just use an IDE and press 'F5' ;P

Compiling by hand is for masochists.

I can't thank you enough, Disch, I wouldn't have trusted my code enough to look to problems elsewhere whitout your guidance.


Glad to help! ^^
Topic archived. No new replies allowed.