2011-12-18 108 views
0

我有這個類棋盤,這裏是它的頭:析構函數和指針類屬性

class ChessBoard 
{ 
    Field** board; 
    Color currentColor; 

public: 
    ChessBoard(); 
    ChessBoard(const ChessBoard&); 
    Field* findField(std::string); 
    ChessBoard& operator = (const ChessBoard&); 

    bool checkIfFieldHasFigure(std::string); 


    void writeOneState(SahApi*); 
    void playAllMoves(std::istream*, SahApi*); 
    void playMove(std::string); 
    ~ChessBoard(); 

}; 

我有它的構造函數,它創建棋盤的開始階段:(相當醜陋,我知道:))

ChessBoard::ChessBoard() 
{ 
    int i, j; 
    Error err; 
    board = new Field*[8]; 
    if(!board) 
    { 
     err.writeToOutput(1); 
     exit(1); 
    } 
    for(i = 0; i < 8; i++) 
    { 
     board[i] = new Field[8]; 
     if(!board[i]) 
     { 
      err.writeToOutput(1); 
      exit(1); 
     } 
    } 
    currentColor = WHITE; 
    char c; 
    std::string s; 
    Figure f; 
    for(i = 0; i < 8; i++) 
     for(j = 0; j < 8; j++) 
     { 
      s.clear(); 
      c = i + 'A'; 
      s.push_back(c); 
      c = j + '1'; 
      s.push_back(c); 
      board[i][j].position.assign(s); 

      if((j > 1) && (j < 6)) 
       board[i][j].hasFigure = 0; 
      else board[i][j].hasFigure = 1; 

      if((i+j+2) % 2) 
       board[i][j].color = WHITE; 
      else board[i][j].color = BLACK; 

      if(((j==0)||(j==7)) && ((i==0)||(i==7))) 
      { 
       Rook* r = new Rook(((j==0)?WHITE:BLACK), s); 
       if(!r) 
       { 
        err.writeToOutput(1); 
        exit(1); 
       } 
       board[i][j].putFigure(r); 
      } 
      else if(((i==1)||(i==6)) && ((j==0)||(j==7))) 
      { 
       Knight* n = new Knight(((j==0)?WHITE:BLACK), s); 
       if(!n) 
       { 
        err.writeToOutput(1); 
        exit(1); 
       } 
       board[i][j].putFigure(n); 
      } 
      else if(((i==2)||(i==5)) && ((j==0)||(j==7))) 
      { 
       Bishop* b = new Bishop(((j==0)?WHITE:BLACK), s); 
       if(!b) 
       { 
        err.writeToOutput(1); 
        exit(1); 
       } 
       board[i][j].putFigure(b); 
      } 
      else if((i==3) && ((j==0)||(j==7))) 
      { 
       Queen* q = new Queen(((j==0)?WHITE:BLACK), s); 
       if(!q) 
       { 
        err.writeToOutput(1); 
        exit(1); 
       } 
       board[i][j].putFigure(q); 
      } 
      else if((i==4) && ((j==0)||(j==7))) 
      { 
       King* k = new King(((j==0)?WHITE:BLACK), s); 
       if(!k) 
       { 
        err.writeToOutput(1); 
        exit(1); 
       } 
       board[i][j].putFigure(k); 
      } 
      else if((j==1) || (j==6)) 
      { 
       Pawn* p = new Pawn(((j==1)?WHITE:BLACK), s); 
       if(!p) 
       { 
        err.writeToOutput(1); 
        exit(1); 
       } 
       board[i][j].putFigure(p); 
      } 
     }  
} 

我也需要有一個化ChessBoard析構函數,這是這樣的:

ChessBoard::~ChessBoard() 
{ 
    //for(int i = 0; i < 8; i++) 
    // delete board[i]; 
    delete [] board; 
} 

它的原因部分被註釋掉是我的第一個問題:

1.爲什麼我不能用上面的書寫方法刪除所有的字段?當我嘗試這樣做時,程序進入「塊類型有效」錯誤,我知道這是由於嘗試刪除不存在的內存引起的。當我發表評論時,該程序完美運行。 ChessBoard是一個矩陣8x8,所以我應該能夠像我在這裏嘗試刪除它。

我的第二個問題是:

2.如何刪除指針圖(國王,王后,車,...)存在於我的構造函數棋盤?這是令人困惑的,因爲這些指針被用作我的國際象棋棋盤的一部分,我使用它們直到程序結束。當程序結束時,我需要釋放我的內存,但我不知道如何訪問這些指針。數字本身會被自動刪除,因爲它們都是非指針。 我甚至需要刪除那些指針,看到我使用它們直到最後,然後一切都被釋放?

+1

這功課嗎?如果沒有,爲什麼不使用適當的固定大小的數組('Field board [8] [8];'),並節省動態內存管理容易出錯的麻煩? – ildjarn

+0

不需要檢查'new'是否返回'NULL' - 這絕不會發生。 –

+0

也不需要動態分配或使用繼承。如果你這樣做是一種有趣的練習,那就不要理會我,但是如果速度很重要(這將是一個AI),那麼一組枚舉就會快得多。 –

回答

6
  1. 新/刪除的一般規則是呼叫必須相互匹配。你有

    board = new Field*[8]; 
    for(i = 0; i < 8; i++) 
    { 
        board[i] = new Field[8]; 
    } 
    

    你將需要刪除您的主板相同的方式來創建你的董事會,但反向:

    for(i = 0; i < 8; i++) 
    { 
        delete [] board[i]; 
    } 
    delete[] board; 
    

    因爲這是不工作我猜你的問題是雙重刪除。別的東西正在釋放陣列。是否有可能你有一個指向同一個Field **的ChessBoard副本?

  2. 你將不得不以類似的方式刪除你的數字。

    for (int x = 0; x < 8; x ++) 
    for (int y = 0; y < 8 ;y ++) 
    if (board[y][x] != NULL) 
        delete board[y][x]; 
    

    只要該代碼將作爲你的代碼以去除電路板上的數字刪除這一數字,並將這一數字爲NULL的位置。

    2b。你的第二個問題的第二部分是你是否必須做任何刪除操作,因爲程序正在結束。你是對的,因爲如果你要馬上退出,你不需要刪除任何東西,操作系統會爲你釋放所有的內存。

通常應該不過,通常你結束了,讓他們運行多次修改大部分程序,然後你會有內存泄漏的每次運行使用稍有更多的內存。


這就是如何解決你問的問題。 但是,我會強烈建議您更改大部分代碼的樣式並刪除所有動態分配。

首先,使用常規的靜態大小數組(Field [8] [8])來存儲該字段。我的意思是,國際象棋什麼時候會改變尺寸?

其次,按價值存儲件。如果某件作品位於某個位置,則該字段類已存儲。也有Field類存儲一個代表類型的枚舉。 沒有理由爲你的作品使用動態分配。

三,沒有必要檢查new的返回是否爲NULL。如果出現錯誤,它將拋出異常,並且程序將停止(因爲它應該在內存不足時沒有太多的工作)。

+0

非常感謝你!不過,我遇到了'ChessField'析構函數的問題。也就是說,如果我改變它到你的建議,如:for(i = 0; i <8; i ++){delete [] board [i]; }刪除[] board;',程序運行完好,當它結束一個錯誤(塊類型有效)時出現。我甚至說過(如果board [i]!= NULL),但它仍然給我錯誤。 – Vidak

+0

@Vidak拍攝,我的壞並沒有完全解讀這個問題。如果我不得不猜測它被雙刪除。你有兩個ChessBoard使用相同的數組或其他東西嗎? – Lalaland

+0

不,我只有一個拷貝構造函數_defined_用於我的棋盤,但我從來沒有在任何地方使用它......我只有一個棋盤的實例,並且在整個程序中我只用它一次。另外,爲什麼'if(board [i]!= NULL)'子句處理這個問題呢?如果它被刪除,它將是空的吧?如果不是,它應該是可刪除的? – Vidak