关于字符的C ++初学者问题

时间:2010-04-26 18:59:57

标签: c++

我只是在试图制作一个简单的井字游戏时正在搞乱一些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,它打印出一些我不认识的奇怪字符。

谁能告诉我为什么? :)

提前致谢。

4 个答案:

答案 0 :(得分:5)

Board::getSquare方法返回Square对象的副本。复制的pState对象的Square变量指向与原始Square对象相同的字符。复制的Square对象被销毁时,会删除char变量指向的pState对象。这会使charSquare对象中的Board对象无效。当您打印时,您正在打印无效的char对象。

正如其他人所说,pState变量应该是char而不是char*。这将使您在解决问题方面向前迈出一步。您仍然需要处理返回对Square对象的引用而不是Square对象的副本。

答案 1 :(得分:4)

  1. 您无需使用new来创建变量实例。

  2. 尝试将状态变量更改为char而不是char *(指向char的指针)。

  3. 通常,char *类型用于表示由空字符终止的字符集合(数组)。

  4. 此外,setstd命名空间中的数据类型。只需将名称更改为其他名称,例如new_value

  5. getState()方法返回状态的副本,而不是对状态的引用。这与Java和C ++有所不同。尝试返回State&,这是C ++术语,用于引用State实例。

  6. 你的节目对于Tic-Tac-Toe游戏来说有点矫枉过正; 古代使用了char的数组,而不是名为OO的新形式的东西。

答案 2 :(得分:3)

Square Board::getSquare(short x, short y) const {
    return board[x][y];
}

在这里,您正在撤回Square实例的副本。由于没有复制构造函数,因此实例将按内存值复制。所以现在有2个Square实例,状态指向相同的值。

但Square有析构函数。在析构函数中,状态指针被删除。但是剩下的副本现在拥有一个悬空指针。

  1. 创建方形实例 A
  2. 分组指针 pA 已分配并设置为' ',因为 A 已创建。

    +-----+
    | pA -----> ' '
    +-----+
    
  3. 临时方形实例 B 是从getSquare中的 A 进行位复制的。这意味着它的char指针 pB 指向 pA 的相同位置

    +-----+        
    | pA -----> ' '
    +-----+      ^
    +-----+      |
    | pB --------'
    +-----+
    
  4. 方形实例 B 是setState到'1',因此pB的内容更改为'1'

    +-----+        
    | pA -----> '1'
    +-----+      ^
    +-----+      |
    | pB --------'
    +-----+  *pB='1'
    
  5. 临时Square实例 B 已被销毁,因为它是暂时的。

    +-----+        
    | pA -----> garbage
    +-----+      ^
    + - - +      |
    : pB --------'
    + - - +  delete pB
    
  6. 现在 pA 指向垃圾。

    +-----+        
    | pA -----> garbage
    +-----+
    

  7. 您应该返回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)