2013-02-18 53 views
1

我想用C++编写一个国际象棋游戏。如何在引用基类对象的向量中引用派生对象?

我有一个基类gamePiece和派生类的白嘴鸦。我最初的想法是创建一个gamePiece对象的向量,并在其中插入所有不同类型的gamePieces(白嘴鸦,皇后,典当)。正如我在最后一个问题中发现的那样,我不能这么做 - gamePiece矢量只能使用基类(即gamePiece)对象。

但是,建议使用智能指针和其他技术。我会尽快尝试。

但我仍然好奇为什么下面的技术将无法正常工作。如果我改为创建一个指向gamePieces的指针向量,然后尝试将指向我的派生对象的指针存储在该向量内呢?

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

例如,假设我在 第一位置插入一个指向上述载体内的车对象。最初我认为可能的工作是这种策略:

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

构造函数似乎运行良好,一切都初始化。但是,当用cout在屏幕上显示数据成员的值时,变量似乎是空的/单元化的。就像他们消失了一样。

我的第二个破解就是试图在插入向量之前动态地将白嘴鸦指针指向游戏手指指针,就像这样。

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

但是,这产生了与上述完全相同的输出。空/单元化变量。

在我第三次尝试时,我退后一步,尝试了一个更简单的操作。在这里,我试图在向量中插入一个指向gamePiece的指针,而不是指向一个白嘴鸦的指针。

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

有甚至第三operation--问题,只有一些我在构造函数初始化的时候我试图显示操作被保留的变量:

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

更具体地说,整型,和字符被保留并正确显示。但弦乐空荡荡的,消失了。

任何人有任何想法,为什么我的策略不工作?

回答

0

您正在推送临时对象的地址。在您检索并取消引用该指针时,该临时变量不再有效。

这是未定义的行为。

您需要持久化对象,或者将它们分配给new,否则在您需要持续时间的有效范围内静态创建它们。

0

你的问题是你正在接收一个临时对象的地址并将它存储在你的std::vector中,那么这个对象就会被销毁,并且你将指向一个无效的对象。

rook(1, "Rook", 'A', 1, "White", "Up")构建一个临时rook对象,你采取的与&push_back其地址为vectorOfPointersToGamePieces。那个临时的rook已经不在行的末尾,vectorOfPointersToGamePieces中的指针仍然悬空。用该指针做任何事情都会导致未定义的行为。

你可能需要动态分配你的rook对象,像这样:

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

但是,你需要确保你delete它,当你用它做。这就是为什么人们告诉你使用std::shared_ptr(或std::unique_ptr)。如果你有一个std::vector<std::shared_ptr<gamePiece>>,那么你可以做到上述路线,并且从不担心物体。

顺便说一句,命名std::vector<gamePiece*>vectorOfPointersToGamePieces似乎有点傻,是不是?变量的名称应该描述它在抽象问题级别,而不是其基础类型。你最好只是叫它gamePieces

0

现在您正在将临时对象的地址存储到您的向量中。只要该语句执行完毕,临时对象就会被销毁,所以指针不再有效。当你试图解引用这些指针时,你会得到未定义的行为。

如果您要在向量中存储指针,则几乎需要动态分配对象,例如使用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似乎是合理的)。这确实会摆脱你未定义的行为 - 它只是让你手动管理内存的工作,这是更好的避免。

0

所有这些尝试都创建并存储指向临时表达式的指针。然后,当您稍后尝试使用指针时,您会看到“未定义行为”。

要动态创建对象,请使用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)); 

OR,

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

由于有片小,固定数量,只是创建他们。然后将他们的地址放入向量中。不需要智能指针。

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

std::vector<game_piece*> whites_pieces; 
whites_pieces.push_back(&white_kings_rook); 
相关问题