交换向量元素与指针从一个派生类到另一个派生类

时间:2012-03-21 20:17:31

标签: c++ pointers stl vector polymorphism

我有一个国际象棋游戏,最初使用stl列表来存储我转换为矢量以获得更好性能的棋子。我知道向量不支持多态,所以为了解决这个问题,我存储的是<Unit *>而不是<Unit>的向量。我的所有棋子对象(Pawn,Rook,Bishop等)都继承自Unit类。

然而,矢量和堆损坏似乎仍然存在问题。我想我已将其追溯到以下功能:

Unit *ChessGame::PromoteUnit(Unit *_oldUnit, UnitType _newType)
{

vector<Unit *> &army = (_oldUnit->m_gameColor == WHITE) ? m_whiteArmy : m_blackArmy;
Unit *newUnit = NULL;

for (unsigned int i = 0; i < army.size(); ++i)
{
    if (army[i]->m_subId == _oldUnit->m_subId)
    {
        if (_newType == QUEEN && _oldUnit->m_gameColor == WHITE)
        {
            newUnit = new Queen(*_oldUnit);
            newUnit->ActiveTexture_(m_textureMan->TextureId_(WhiteQueen));
        }
        else if (_newType == KNIGHT && _oldUnit->m_gameColor == WHITE)
        {
            newUnit = new Knight(*_oldUnit);
            newUnit->ActiveTexture_(m_textureMan->TextureId_(WhiteKnight));
        }
        else if (_newType == QUEEN && _oldUnit->m_gameColor == BLACK)
        {
            newUnit = new Queen(*_oldUnit);
            newUnit->ActiveTexture_(m_textureMan->TextureId_(BlackQueen));
        }
        else if (_newType == KNIGHT && _oldUnit->m_gameColor == BLACK)
        {
            newUnit = new Knight(*_oldUnit);
            newUnit->ActiveTexture_(m_textureMan->TextureId_(BlackKnight));
        }

        newUnit->m_wasPawn = true;
        delete army[i];
        army[i] = newUnit;
        break;
    }
}

m_selectedUnit = newUnit;

return newUnit;
}

由于指针只有4个字节而不管它指向的是什么,因此在这种情况下stl向量仍然存在问题的原因是什么?我的Pawn对象的大小比被提升的骑士或女王大8个字节,这或许可以解释我一直得到的奇怪的内存错误。当我备份我的回合历史并点击我的降级功能以反转促销时:

Unit *ChessGame::DemoteUnit(Unit *_oldUnit, UnitType _newType)
{
COUT("ChessGameManager::_DemoteUnit(Unit *, UnitType)");

vector<Unit *> &army = (_oldUnit->m_gameColor == WHITE) ? m_whiteArmy : m_blackArmy;
Unit *newUnit = NULL;

for (unsigned int i = 0; i < army.size(); ++i)
{
    if (army[i]->m_subId == _oldUnit->m_subId)
    {
        newUnit = new Pawn();
        newUnit->m_wasPawn = false;

        if (_oldUnit->m_gameColor == WHITE)
            newUnit->ActiveTexture_(m_textureMan->TextureId_(WhitePawn));

        newUnit->m_gameColor = _oldUnit->m_gameColor;
        newUnit->MobilityValid_(false);
        newUnit->Color_(RvColor::ClrWhite);
        newUnit->m_square = _oldUnit->m_square;
        newUnit->m_captured = false;
        newUnit->m_origin = _oldUnit->m_origin;
        newUnit->m_subId = _oldUnit->m_subId;
        newUnit->m_visible = true;

        //newUnit->m_square->m_unit = newUnit;

        delete army[i];
        army[i] = newUnit;
        break;
    }
}

return newUnit;
}

它真的崩溃了:

newUnit = new Pawn();

当它尝试使用malloc来保留堆内存时,单步执行新的Pawn()会导致它在new运算符内崩溃。无论如何我认为它仍然与我对矢量stl如何工作缺乏完全理解有关。我知道它与我的Pawn()构造函数无关,因为它在游戏板初始化期间被多次调用。

1 个答案:

答案 0 :(得分:0)

我怀疑,但无法从您分享的信息中证明,ChessGame的复制构造函数和复制赋值运算符执行m_whiteArmym_blackArmy的浅层副本。 (注意:如果您没有提供复制构造函数或复制赋值运算符,编译器会为您提供它们。编译器提供的那些运算符可以执行浅复制。)

您违反了Rule of Three

您可以通过以下方式解决此问题:

  • 从不复制ChessGame对象。
  • 通过以下方式执行上述操作:
    • (pre-C ++ 11):声明并且不定义复制构造函数和复制赋值运算符。
    • (C ++ 11):在复制构造函数和复制赋值运算符声明之后指定= delete
  • 更改指向智能指针的指针(如std::shared_ptr)。或
  • 在复制构造函数和复制赋值运算符中实现深层复制。