将具有指针的向量元素从一个派生类交换到另一派生类
swapping vector element with a pointer from one derived class to another
我有一个国际象棋游戏,最初使用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来保留堆内存时,进入new Pawn()会导致它在新操作符内崩溃。无论如何,我认为这仍然与我对向量stl的工作原理缺乏完全理解有关。我知道它与我的Pawn()构造函数无关,因为它在游戏板初始化期间被调用了很多次。
我怀疑,但无法从您共享的信息中证明,ChessGame
的复制构造函数和复制赋值运算符正在执行m_whiteArmy
和m_blackArmy
的浅层复制。(注意:如果你没有提供复制构造函数或复制赋值运算符,编译器会为你提供它们。编译器提供的是浅层复制。)
你违反了三条规则。
您可以通过以下方式解决此问题:
- 从不复制
ChessGame
对象 - 通过以下方式执行上述规定:
- (C++11之前):声明和不定义复制构造函数和复制赋值运算符
- (C++11):在复制构造函数和复制赋值运算符声明之后指定
= delete
- 将指针更改为智能指针(如
std::shared_ptr
)。,或 - 在复制构造函数和复制赋值运算符中实现深度复制
相关文章:
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 检查一个类型是否直接派生自"enable if"上下文中的另一个类型(是其子类型)
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- C++重载函数,一个采用基类的参数,另一个采用派生类的参数
- C ++如何在原始抽象类中创建一个函数,该函数接受派生类的输入
- 如何将一个变量用于父类和派生类
- 两个抽象类,派生自同一个基类.如何访问从一个抽象类到另一个抽象类的指针
- 用于从一个基派生的类的GDB漂亮的打印机
- 存储在一个通用容器中的派生对象.如何避免铸造
- C++多态性:如何测试一个类是否派生自另一个基类
- 派生类不能用另一个基类的成员重载基类中的私有成员
- 通过 c++ 中的 udp 套接字将派生类对象从一个进程发送到另一个进程
- 是否可以在引用另一个派生类的派生类中声明复制构造函数?
- 如果我们有一个基*类,如何访问派生模板类的成员函数
- 无法从派生类型的作用域访问另一个实例的受保护成员
- C 有一个关键字,允许从派生类引用基本类型
- 从一个函数和某些类型指定符定义整个派生类的宏
- 是否有可能有一个派生类继承最终函数但创建相同的函数(而不是重写)
- 在C++中从模板类本身派生一个模板类
- 在c++中基于另一个变量类型派生一个变量类型