gpt4 book ai didi

c++ - 如何实现具有循环引用的对象的深拷贝或克隆?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:41:34 25 4
gpt4 key购买 nike

我有这样的层次结构:

class Sphere;
class Cube;
class SpherePair;

class Entity {};

class Cube : public Entity {
public:
list<Sphere*> spheres_;
};

class Sphere : public Entity {
public:
Cube *cube;
SpherePair *spherepair;
};

class SpherePair : public Entity {
public:
Sphere *first;
Sphere *second;
};

我想要的是克隆 Cube 对象和所有连接到它的对象(Sphere、SpherePair、Cube)。

Cube 内部有 Spheres,每个 Sphere 是 SpherePair 对象的一半。 SpherePair 指向位于不同立方体或同一个立方体中的球体。

这是正确撤消功能所必需的。

我还想要一张旧实体和克隆实体的 map :

std::map<Entity*, Entity*> old_new;

添加:在这些循环引用之前,我有一个简单的克隆功能:

class Entity {
public:
virtual Entity* clone() = 0;
}

它被用在这样的方案中:

std::vector<Entity*> selected_objects_;

void move(const vec3f &offset) {
document->beginUndo();

for(int i = 0; i < selected_objects_.size(); ++i) {
Entity *cloned = selected_objects_[i]->clone();

cloned->move(offset);

selected_objects_[i]->setDeleted(true);
document->pushToUndo(selected_objects_[i]);
document->addEntity(cloned);
}

document->endUndo();
}

最佳答案

我将发布整个代码块作为答案:

#include <iostream>
#include <list>
#include <map>

#include <assert.h>

using std::cout;
using std::endl;
using std::list;
using std::make_pair;
using std::map;
using std::pair;

class Cube;
class Sphere;
class SpherePair;

class Entity {
public:
virtual ~Entity() {}
virtual Entity* clone() { return 0; }
virtual Entity* cloneDeep(map<Entity*, Entity*> *old_new) { return 0; }

protected:
bool cloneAndPush(Entity *e, map<Entity*, Entity*> *old_new) {
if (0 != old_new->count(e)) {
return false; // already cloned
}

typedef pair<map<Entity*, Entity*>::iterator, bool> insert_result;
Entity *cloned = e->clone();
insert_result inserted = old_new->insert(std::make_pair(e, cloned));
assert(inserted.second);
return inserted.second;
}
};

class Sphere : public Entity {
public:
Sphere() {
cout << "constructor Sphere" << endl;
}
virtual ~Sphere() {
cout << "destructor Sphere" << endl;
}
virtual Entity* clone();
virtual Entity* cloneDeep(map<Entity*, Entity*> *old_new);

Cube *cube;
SpherePair *spherepair;
};

class Cube : public Entity {
public:
Cube() {
cout << "constructor Cube" << endl;
}
virtual ~Cube() {
cout << "destructor Cube" << endl;
}
virtual Entity* clone() {
cout << "clone Cube" << endl;
Cube *c = new Cube(*this);
c->spheres_.clear();
return c;
}

virtual Entity* cloneDeep(map<Entity*, Entity*> *old_new) {
if (cloneAndPush(this, old_new)) {
Cube *c = static_cast<Cube*>((*old_new)[this]);
for(list<Sphere*>::iterator i = spheres_.begin(); i != spheres_.end(); ++i) {
c->addSphere(static_cast<Sphere*>((*i)->cloneDeep(old_new)));
}
}

return old_new->operator[](this);
}

void addSphere(Sphere *s) {
spheres_.push_back(s);
}

void delSphere(Sphere *s) {
spheres_.remove(s);
}

list<Sphere*> spheres_;
};

class SpherePair : public Entity {
public:
SpherePair() {
cout << "constructor SpherePair" << endl;
}
virtual ~SpherePair() {
cout << "destructor SpherePair" << endl;
delete first;
delete second;
}

virtual Entity* clone() {
cout << "clone SpherePair" << endl;
return new SpherePair(*this);
}

virtual Entity* cloneDeep(map<Entity*, Entity*> *old_new) {
if (cloneAndPush(this, old_new)) {
SpherePair *s = static_cast<SpherePair*>((*old_new)[this]);
s->first = (Sphere*)first->cloneDeep(old_new);
s->second = (Sphere*)second->cloneDeep(old_new);
}

return (*old_new)[this];
}

Sphere *first;
Sphere *second;
};

Entity* Sphere::clone() {
cout << "clone Sphere" << endl;
return new Sphere(*this);
}

Entity* Sphere::cloneDeep(map<Entity*, Entity*> *old_new) {
if (cloneAndPush(this, old_new)) {
Sphere *s = static_cast<Sphere*>((*old_new)[this]);
s->cube = (Cube*)cube->cloneDeep(old_new);
s->spherepair = (SpherePair*)spherepair->cloneDeep(old_new);
}

return (*old_new)[this];
}

inline void populateListSimpleCase(list<Entity*> *ents) {
Cube *first_cube = new Cube;
Cube *second_cube = new Cube;
// Cube *third_cube = new Cube;
ents->push_back(first_cube);
ents->push_back(second_cube);

for (int i = 0; i < 3; ++i) {
Sphere *first_cube_spheres = new Sphere;
Sphere *second_cube_spheres = new Sphere;
first_cube->addSphere(first_cube_spheres);
first_cube_spheres->cube = first_cube;

second_cube->addSphere(second_cube_spheres);
second_cube_spheres->cube = second_cube;

SpherePair *sp = new SpherePair;
sp->first = first_cube_spheres;
sp->second = second_cube_spheres;
ents->push_back(sp);
first_cube_spheres->spherepair = sp;
second_cube_spheres->spherepair = sp;
}
}

int main(int argc, char* argv[]) {
list<Entity*> ent_list;
populateListSimpleCase(&ent_list);

map<Entity*, Entity*> old_new;
(*ent_list.begin())->cloneDeep(&old_new);

for (list<Entity*>::iterator i = ent_list.begin(); i != ent_list.end(); ++i){
delete (*i);
}
ent_list.clear();

return 0;
}

关于c++ - 如何实现具有循环引用的对象的深拷贝或克隆?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6214268/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com