C ++ beginner question regarding symbols
I was just messing around with some C ++ for now trying to make a simple tic-tac-toe game and I ran into some problem. This is my code:
#include <iostream>
using namespace std;
class Square {
public:
char getState() const;
void setState(char);
Square();
~Square();
private:
char * pState;
};
class Board {
public:
Board();
~Board();
void printBoard() const;
Square getSquare(short x, short y) const;
private:
Square board[3][3];
};
int main() {
Board board;
board.getSquare(1,2).setState('1');
board.printBoard();
return 0;
}
Square::Square() {
pState = new char;
*pState = ' ';
}
Square::~Square() {
delete pState;
}
char Square::getState() const {
return *pState;
}
void Square::setState(char set) {
*pState = set;
}
Board::~Board() {
}
Board::Board() {
}
void Board::printBoard() const {
for (int x = 0; x < 3; x++) {
cout << "|";
for (int y = 0; y < 3; y++) {
cout << board[x][y].getState();
}
cout << "|" << endl;
}
}
Square Board::getSquare(short x, short y) const {
return board[x][y];
}
Forgive me if there are frankly obvious problems with it or if it is stupidly written, this is my first C ++ program: p However, the problem is that when I try to set the square of 1.2 to char '1', it does not print as 1 , it prints like some weird character that I didn't recognize.
Can anyone tell me why? :)
Thanks in advance.
a source to share
-
You don't need to use
new
to instantiate variables. -
Try changing your state variable to
char
instead ofchar *
(pointer tochar
). -
In general, a type is
char *
used to indicate a collection (array) of nul-terminated characters. -
It is also
set
a data type in a namespacestd
. Just change the name to something else, egnew_value
. -
The method
getState()
returns a copy of the state, not a reference to the state. This is where Java and C ++ differ. Try to returnState&
which is C ++ language to reference the State instance. -
Your program is a little overloaded for Tic-Tac-Toe; the ancients used arrays
char
instead of this new style called OO.
a source to share
The method Board::getSquare
returns a copy of the object Square
. The pState
copied object variable Square
points to the same symbol as the original object Square
. When the copied object is Square
destroyed, it deletes the object char
pointed to by the variable pState
. This will override the object char
in the object Square
in Board
. When you go to print, you are printing an invalid object char
.
As others have pointed out, the variable pState
should probably be char
, not char*
. This will take you a step further in solving your problems. You still need to deal with returning an object reference Square
rather than a copy of the object Square
.
a source to share
Square Board::getSquare(short x, short y) const {
return board[x][y];
}
This is where you keep an instance of a copy of the Square instance. Since there is no constructor , the instance will be copied by memory value. So now there are 2 squares that the state points to the same value.
But the square has a destructor . In the destructor, the state pointer is removed. But then the remaining copy now has a dangling pointer.
- A square instance of A.
-
The Char pointer pA is allocated and set
' '
to as A.+-----+ | pA -----> ' ' +-----+
-
The temporary square of instance B is bit-copied from A to
getSquare
. This means that the char pointer pB points to the same location pA+-----+ | pA -----> ' ' +-----+ ^ +-----+ | | pB --------' +-----+
-
The square instance of B is set
'1'
toState, so the content of pB changes to'1'
+-----+ | pA -----> '1' +-----+ ^ +-----+ | | pB --------' +-----+ *pB='1'
-
Instance B's temporary square is destroyed because, well, it's temporary.
+-----+ | pA -----> garbage +-----+ ^ + - - + | : pB --------' + - - + delete pB
-
Now pA points to garbage.
+-----+ | pA -----> garbage +-----+
You have to return reference to avoid copying,
Square& Board::getSquare(short x, short y) { return board[x][y]; }
//----^ "&" means reference. Similar to pointer, but not rebindable/nullable.
// Just think of it as a read-only pointer without needing a "*"
const Square& Board::getSquare(short x, short y) const { return board[x][y]; }
// Both mutable and const versions are needed. (Yes, code duplication.)
and / or provide a copy constructor.
class Square {
public:
...
Square(const Square&);
...
Square::Square(const Square& other) {
pState = new char;
*pState = *other.pState;
}
You can just use
class Square {
public:
char getState() const; // { return state; }
void setState(char); // { state = input; }
private:
char state;
};
to avoid heap memory mess. cout <<
supports printing char
.
And please don't write C ++ in Java.
a source to share
Two problems:
1) The method getSquare
is equal const
and therefore returns an object const
.
1) Method getSquare
const
and therefore cannot return a reference const
for a const object.
2) The object returned from getSquare
is a copy of the square on the board.
To fix it:
1) Remove const
from the method getSquare
.
2) change getSquare
to get the link back:Square & Board::getSquare(short x, short y)
a source to share