I'm just messing around with some C++ at the moment trying to make a simple tic-tac-toe game and I'm running into a bit of a 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;开发者_如何学Python
*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 blatantly obvious problems with it or it's stupidly written, this is my first program in C++ :p However, the problem is that when I try and set the square 1,2 to the char '1', it doesn't print out as a 1, it prints out as some strange character I didn't recognise.
Can anyone tell me why? :)
Thanks in advance.
The Board::getSquare
method is returning a copy of the Square
object. The pState
variable of the copied Square
object points to the same character as the original Square
object. When the copied Square
object is destroyed, it deletes the char
object pointed to by the pState
variable. This invalidates the char
object in the Square
object in the Board
. When you go to print, you are printing an invalid char
object.
As others has stated, the pState
variable should probably be a char
rather than a char*
. This will move you a step forward in resolving your issues. You still need to deal with returning a reference to the Square
object rather than a copy of the Square
object.
You don't need to use
new
for creating instances of variables.Try changing your state variable to
char
instead ofchar *
(pointer tochar
).In general, the
char *
type is used to indicate a collection (array) of characters terminated by a nul character.Also,
set
is a data type in thestd
namespace. Just change the name to something else, such asnew_value
.The
getState()
method is returning a copy of the state, not a reference to the state. This where Java and C++ differ. Try returning aState&
, which is C++ jargon for a reference to a State instance.Your program is a bit overkill for a Tic-Tac-Toe game; the ancient ones used arrays of
char
instead of this new fashioned stuff called OO.
Square Board::getSquare(short x, short y) const {
return board[x][y];
}
In here, you are returing a copy of the Square instance. Since there is no copy constructor, the instance will be copied by memory value. So now there are 2 Square instances which the state points to the same value.
But a Square has a destructor. In the destructor, the state pointer is deleted. But then the remaining copy now owns a dangling pointer.
- Square instance A is created.
Char pointer pA is allocated and set to
' '
as A is created.+-----+ | pA -----> ' ' +-----+
Temporary Square instance B is bit-copied from A in
getSquare
. That means its char pointer pB points to the same location of pA+-----+ | pA -----> ' ' +-----+ ^ +-----+ | | pB --------' +-----+
Square instance B is setState to
'1'
, so the content of pB is changed to'1'
+-----+ | pA -----> '1' +-----+ ^ +-----+ | | pB --------' +-----+ *pB='1'
The temporary Square instance B is destroyed because, well, it's temporary.
+-----+ | pA -----> garbage +-----+ ^ + - - + | : pB --------' + - - + delete pB
Now pA points to garbage.
+-----+ | pA -----> garbage +-----+
You should return a 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 messing with heap memories. cout <<
supports printing a char
.
And please don't write C++ in Java.
Two problems:
1) The getSquare
method is const
and so returns a const
object.
1) The getSquare
method is const
and so cannot return a non-const
reference to a const object.
2) The object returned from getSquare
is a copy of the square in the board.
To fix:
1) Remove the const
from the getSquare
method.
2) alter getSquare
to return a reference: Square & Board::getSquare(short x, short y)
精彩评论