我只是在试图制作一个简单的井字游戏时正在搞乱一些C ++,而我遇到了一些问题。这是我的代码:
#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];
}
请原谅我,如果它有明显的明显问题或者是愚蠢的写,这是我在C ++中的第一个程序:p然而,问题是当我尝试将方形1,2设置为char'1'时,它不打印为1,它打印出一些我不认识的奇怪字符。
谁能告诉我为什么? :)
提前致谢。
答案 0 :(得分:5)
Board::getSquare
方法返回Square
对象的副本。复制的pState
对象的Square
变量指向与原始Square
对象相同的字符。复制的Square
对象被销毁时,会删除char
变量指向的pState
对象。这会使char
中Square
对象中的Board
对象无效。当您打印时,您正在打印无效的char
对象。
正如其他人所说,pState
变量应该是char
而不是char*
。这将使您在解决问题方面向前迈出一步。您仍然需要处理返回对Square
对象的引用而不是Square
对象的副本。
答案 1 :(得分:4)
您无需使用new
来创建变量实例。
尝试将状态变量更改为char
而不是char *
(指向char
的指针)。
通常,char *
类型用于表示由空字符终止的字符集合(数组)。
此外,set
是std
命名空间中的数据类型。只需将名称更改为其他名称,例如new_value
。
getState()
方法返回状态的副本,而不是对状态的引用。这与Java和C ++有所不同。尝试返回State&
,这是C ++术语,用于引用State实例。
你的节目对于Tic-Tac-Toe游戏来说有点矫枉过正; 古代使用了char
的数组,而不是名为OO的新形式的东西。
答案 2 :(得分:3)
Square Board::getSquare(short x, short y) const {
return board[x][y];
}
在这里,您正在撤回Square实例的副本。由于没有复制构造函数,因此实例将按内存值复制。所以现在有2个Square实例,状态指向相同的值。
但Square有析构函数。在析构函数中,状态指针被删除。但是剩下的副本现在拥有一个悬空指针。
分组指针 pA 已分配并设置为' '
,因为 A 已创建。
+-----+
| pA -----> ' '
+-----+
临时方形实例 B 是从getSquare
中的 A 进行位复制的。这意味着它的char指针 pB 指向 pA 的相同位置
+-----+
| pA -----> ' '
+-----+ ^
+-----+ |
| pB --------'
+-----+
方形实例 B 是setState到'1'
,因此pB的内容更改为'1'
+-----+
| pA -----> '1'
+-----+ ^
+-----+ |
| pB --------'
+-----+ *pB='1'
临时Square实例 B 已被销毁,因为它是暂时的。
+-----+
| pA -----> garbage
+-----+ ^
+ - - + |
: pB --------'
+ - - + delete pB
现在 pA 指向垃圾。
+-----+
| pA -----> garbage
+-----+
您应该返回reference以避免复制,
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.)
和/或提供复制构造函数。
class Square {
public:
...
Square(const Square&);
...
Square::Square(const Square& other) {
pState = new char;
*pState = *other.pState;
}
你可以使用
class Square {
public:
char getState() const; // { return state; }
void setState(char); // { state = input; }
private:
char state;
};
避免弄乱堆内存。 cout <<
支持打印char
。
请不要用Java编写C ++。
答案 3 :(得分:2)
两个问题:
1) getSquare
方法为const
,因此返回const
个对象。
1)getSquare
方法为const
,因此无法返回对const对象的非const
引用。
2)从getSquare
返回的对象是棋盘中方格的副本。
修复:
1)从const
方法中删除getSquare
。
2)改变getSquare
以返回引用:Square & Board::getSquare(short x, short y)