开发者

C++ beginner question regarding chars

开发者 https://www.devze.com 2022-12-28 10:21 出处:网络
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:

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.


  1. You don't need to use new for creating instances of variables.

  2. Try changing your state variable to char instead of char * (pointer to char).

  3. In general, the char * type is used to indicate a collection (array) of characters terminated by a nul character.

  4. Also, set is a data type in the std namespace. Just change the name to something else, such as new_value.

  5. The getState() method is returning a copy of the state, not a reference to the state. This where Java and C++ differ. Try returning a State&, which is C++ jargon for a reference to a State instance.

  6. 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.

  1. Square instance A is created.
  2. Char pointer pA is allocated and set to ' ' as A is created.

    +-----+
    | pA -----> ' '
    +-----+
    
  3. 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 --------'
    +-----+
    
  4. Square instance B is setState to '1', so the content of pB is changed to '1'

    +-----+        
    | pA -----> '1'
    +-----+      ^
    +-----+      |
    | pB --------'
    +-----+  *pB='1'
    
  5. The temporary Square instance B is destroyed because, well, it's temporary.

    +-----+        
    | pA -----> garbage
    +-----+      ^
    + - - +      |
    : pB --------'
    + - - +  delete pB
    
  6. 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)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号