我有这样的层次结构:
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/