如何引用在指针基类对象的矢量导出对象?(How to reference derived objec

2019-10-17 17:32发布

我试图建立在C ++的一盘棋。

我有一个基类游戏币和派生类车。 我最初的想法是创建游戏币对象的载体和插入各种不同类型的gamePieces(乌鸦,王后,兵卒)的在里面。 正如我在我的最后一个问题发现了,我不能这样做 - 将游戏币矢量只需要基础类(即游戏币)的对象。

然而,智能指针和其他技术被提出。 我会尽快尝试。

但我,为什么下面的技术将无法正常工作还是很好奇。 如果我而是创建指向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")  ) ) );

但是,这产生了如上完全相同的输出。 空/未初始化变量。

在我的第三次尝试,我向后退了一步,试图更简单的操作。 在这里,我试图插入一个指向游戏币的载体,而不是一个指向车。

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

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

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

更具体地,整数,和焦炭被保留和正常显示。 但字符串是空的,就消失了。

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

Answer 1:

你的问题是,你正在做一个临时对象的地址并将其存储在您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"));

但是,你需要确保你delete它,当你用它做。 这就是为什么人们告诉你要使用std::shared_ptr (或std::unique_ptr )。 如果你有一个std::vector<std::shared_ptr<gamePiece>>那么你可以做上面的线,从不担心delete荷兰国际集团的对象。

顺便说一句,命名std::vector<gamePiece*>作为vectorOfPointersToGamePieces似乎有点傻,不是吗? 变量的名称应该是形容它是什么在抽象问题的水平,而不是它的基础类型。 你会更好只是调用它gamePieces



Answer 2:

您正在推动一个临时对象的地址。 到时候你检索和取消引用该指针,暂时不再有效。

这是不确定的行为。

你要的对象是持久的,要么它们分配new ,否则静态地,这将是有效的,你需要它们的持续时间范围内创建。



Answer 3:

现在你存储的临时对象的地址到您的载体。 一旦该语句完成执行后,临时对象被销毁,所以指针不再有效。 当您尝试取消引用这些指针,你得到了一个未定义的行为。

如果你在你的载体去商店的指针,你几乎需要动态分配的对象,如用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在这种情况下,似乎是合理的)。 这并摆脱你的未定义行为虽然 - 它只是让你用手动管理内存的工作,这是更好的避免。



Answer 4:

所有这些努力创建和存储指针临时表达式。 然后,当您稍后尝试使用指针,你会得到未定义的行为。

要动态地创建对象,而不是,用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") );


Answer 5:

由于有片小,固定数量,只是创建他们。 然后把他们的地址到载体。 无需智能指针。

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

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


文章来源: How to reference derived objects in a vector of pointers to base class objects?