1

我有一个基类、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;
}
4

1 回答 1

3

添加一个swap交换容器的成员,然后将分配实现为复制和交换:

void swap(EntityManager& other)
{ theEntities.swap(other.theEntities); }

EntityManager& operator=(EntityManager other)
{ swap(other); return *this; }

赋值运算符的参数将使用您已经编写的复制构造函数复制,然后交换数据,因此*this当该参数超出范围时,属于的数据将被销毁,并*this拥有新复制的数据。

以这种方式重用复制构造函数意味着您只需要实现一个正确的复制构造函数(和正确的交换,这通常很容易正确),并且您的赋值运算符非常简单并且自动正确。

注意,您的init成员和复制 ctor 不是异常安全的,如果任何push_back操作引发异常,您就会泄漏内存。您还缺少一个析构函数,但我认为它存在于真实代码中。

于 2012-06-09T12:44:58.330 回答