我有一个基类,2个派生类和一个entitymanager类,它有一个指向派生对象的基指针容器。我在基础中有一个虚拟克隆方法来处理派生类中的复制构造函数,但是我无法绕过重载赋值运算符并防止切片,有人可以帮助解决这个问题,也许还要检查我是如何处理的entitymanager复制构造函数?我认为没问题
class System
{
public:
virtual System* clone()=0;
};
class projectile :public System
{
public:
projectile* clone()
{
return new projectile(*this);
}
};
class player : public System
{
public:
player* clone()
{
return new player(*this);
}
};
class EntityManager
{
private:
vector<System*> theEntities;
public:
EntityManager(){}
EntityManager(EntityManager& other)
{
for (size_t i=0;i<other.theEntities.size();i++)
theEntities.push_back(other.theEntities[i]->clone());
}
void init()
{
projectile* aProjectile = new projectile;
player* aPlayer = new player;
theEntities.push_back(aProjectile);
theEntities.push_back(aPlayer);
}
};
int main (int argc, char * const argv[])
{
EntityManager originalManager;
originalManager.init();
EntityManager copyManager(originalManager);
return 0;
}
答案 0 :(得分:3)
添加一个交换容器的swap
成员,然后将赋值实现为复制和交换:
void swap(EntityManager& other)
{ theEntities.swap(other.theEntities); }
EntityManager& operator=(EntityManager other)
{ swap(other); return *this; }
赋值运算符的参数将使用您已编写的复制构造函数进行复制,然后交换数据,因此当该参数超出范围时,将销毁属于*this
的数据,并且*this
拥有新复制的数据。
以这种方式重复使用复制构造函数意味着您只需要实现正确的复制构造函数(并且正确的交换,这通常很容易正确),并且您的赋值运算符非常简单并且自动更正。
N.B。如果任何init
操作抛出异常泄漏内存,则push_back
成员和copy ctor都不是异常安全的。你也错过了一个析构函数,但我认为它存在于实际代码中。