簡體   English   中英

如何在指向基類對象的指針向量中引用派生對象?

[英]How to reference derived objects in a vector of pointers to base class objects?

我正在嘗試用C ++構建國際象棋游戲。

我有一個基類gamePiece和一個派生類菜鳥。 我最初的想法是創建一個gamePiece對象的向量,並在其中插入所有不同類型的gamePieces(老虎,皇后,典當)。 正如我在上一個問題中發現的那樣,我無法做到這一點-gamePiece向量僅接受基類(即gamePiece)對象。

但是,建議使用智能指針和其他技術。 我會盡快嘗試。

但是我仍然對以下技術為什么行不通感到好奇。 如果我改為創建一個指向gamePieces的指針的矢量,然后嘗試將指向我的派生對象的指針存儲在該矢量中怎么辦?

vector<gamePiece *> vectorOfPointersToGamePieces;  
vector<gamePiece *>::iterator itOfPointersToGamePieces;

例如,假設我在上述向量中的第一個位置插入了指向rook對象的指針。 最初,我認為可行的策略是:

vectorOfPointersToGamePieces.push_back( &(rook(1, "Rook", 'A', 1, "White", "Up")  ) );
itOfPointersToGamePieces=vectorOfPointersToGamePieces.begin();  
( * ( * (itOfPointersToGamePieces))).displayPieceInfo();

構造函數似乎運行良好,一切都初始化了。 但是,當需要使用cout在屏幕上顯示數據成員的值時,變量似乎是空的/單位化的。 就像他們消失了一樣。

我要解決的第二個難題是嘗試將rook指針動態地轉換為游戲指針,然后再將其插入向量中。

vectorOfPointersToGamePieces.push_back( dynamic_cast <gamePiece *> (&(rook(1, "Rook", 'A', 1, "White", "Up")  ) ) );

但這產生了與上述完全相同的輸出。 空/單元化變量。

在第三次嘗試時,我后退一步,嘗試了一個更簡單的操作。 在這里,我試圖在向量中插入一個指向gamePiece的指針,而不是指向一個rook的指針。

vectorOfPointersToGamePieces.push_back( &(gamePiece(1, "Rook", 'A', 1, "White", "Up")) );

甚至第三個操作都存在問題-嘗試顯示操作時,僅保留了我在構造函數中初始化的一些變量:

itOfPointersToGamePieces=vectorOfPointersToGamePieces.begin();
( * ( * (itOfPointersToGamePieces))).displayPieceInfo();

更具體地說,整數和字符保留並正確顯示。 但是琴弦是空的,消失了。

有人對我的策略為何行不通有任何想法嗎?

您的問題是,您要獲取一個臨時對象的地址並將其存儲在std::vector ,那么該對象將被銷毀,而您將指向無效的對象。

rook(1, "Rook", 'A', 1, "White", "Up")構造一個臨時的rook對象,您可以使用&接收其地址並將其push_backvectorOfPointersToGamePieces 該臨時rook由線到底去了哪里,並在指針vectorOfPointersToGamePieces是左晃來晃去。 用該指針執行幾乎任何操作都會導致未定義的行為。

您可能需要像這樣動態分配您的rook對象:

vectorOfPointersToGamePieces.push_back(new rook(1, "Rook", 'A', 1, "White", "Up"));

但是,您需要確保在完成操作deletedelete 這就是為什么人們告訴您使用std::shared_ptr (或std::unique_ptr )的原因。 如果您有std::vector<std::shared_ptr<gamePiece>>則可以執行上述操作,而不必擔心delete該對象。

順便說一句,將std::vector<gamePiece*>命名為vectorOfPointersToGamePieces似乎有點愚蠢,不是嗎? 變量的名稱應該描述其在抽象問題級別上的含義,而不是其基礎類型。 您最好將其gamePieces

您正在推送臨時對象的地址。 在您檢索和取消引用該指針時,該臨時項不再有效。

這是未定義的行為。

您需要對象是持久性的,或者給它們分配new ,或者在一個范圍內靜態創建它們,該范圍在您需要它們的持續時間內有效。

現在,您正在將臨時對象的地址存儲到向量中。 該語句完成執行后,臨時對象將被銷毀,因此指針不再有效。 當您嘗試取消引用那些指針時,您會得到未定義的行為。

如果要將指針存儲在向量中,則非常需要動態分配對象,例如使用new 換句話說,替換為:

[your_vector].push_back( &(rook(1, "Rook", 'A', 1, "White", "Up")

有:

[your_vector].push_back(new rook(1, "Rook", 'A', 1, "White", "up"))

您將獲得定義的行為。 請注意,我並不是真的建議這樣做-正如您(顯然)已經告訴您的那樣,您可能想使用某種智能指針(例如,在這種情況下, std::unique_ptr似乎很合理)。 但是,這確實擺脫了您未定義的行為-只是讓您承擔了手動管理內存的工作,最好避免這樣做。

所有這些嘗試都會創建並存儲指向臨時表達式的指針。 然后,當您以后嘗試使用指針時,會出現“未定義行為”。

要動態創建對象,請使用new關鍵字(或std::make_shared )。 並使用std::unique_ptrstd::shared_ptr這樣您就不必擔心在學習指針時通常會出錯的一百件事中的一半。

vector<std::unique_ptr<gamePiece>> vectorOfPointersToGamePieces;
std::unique_ptr<gamePiece> rk( new rook(1, "Rook", 'A', 1, "White", "Up") );
vectorOfPointersToGamePieces.push_back(std::move(rk));

要么,

vector<std::shared_ptr<gamePiece>> vectorOfPointersToGamePieces;
vectorOfPointersToGamePieces.push_back(
  std::make_shared<rook>(1, "Rook", 'A', 1, "White", "Up") );

由於數量少且數量固定,因此只需創建它們即可。 然后將其地址放入向量中。 無需智能指針。

rook white_kings_rook(/* whatever */);
// ...

std::vector<game_piece*> whites_pieces;
whites_pieces.push_back(&white_kings_rook);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM