C++如何正确地复制指针的容器(向量)?
有几次我偶然发现了需要复制的指针容器。C++如何正确地复制指针的容器(向量)?
比方说,我们有下面的类层次结构:
-
学生(基类)
- 大一(子类)
- Sophmore(子类)
- 少年(子类)
- 高级(小类)
StudentService
的StudentService类有一个std::vector<Student*> students
场和下面的构造:
StudentService::StudentService(std::vector<Student*> students) {
// code
}
这不会是正确的,只是使用std::vector::operator=
操作和写this->students = students
,因为只会复制指针地址,所以如果外部的某个人删除了这些指针所指向的对象,那么StudentService类就会因此受到影响。
解决的办法是遍历在students
参数每个指针,并创建一个新的动态对象,像这样:
for(int i = 0; i < students.size(); i++) {
this->students.at(i) = new Student(*students.at(i));
}
但即使是不正确的,由于事实,即它只能建立学生对象。我们知道一个学生可以成为新生,Sophmore,初中或高中。所以这是我的问题:什么是这个问题的最佳解决方案?
我想一个办法是将每个学生类中的私有枚举场,并有4 if-else语句检查它是什么类型的学生,然后创建一个基于像这样一个新的动态对象:
for(int i = 0; i < students.size(); i++) {
if(students.at(i).getType() == FRESHMAN) {
this->students.at(i) = new Freshman(*students.at(i));
} else if(students.at(i).getType() == SOPHMORE) {
this->students.at(i) = new Sophmore(*students.at(i));
} else if {
// and so on...
}
}
但是,这仍然看起来很繁琐,所以你会建议什么?
您正在寻找克隆模式。 向学生添加一个clone()虚函数,该函数在每个后代中被覆盖并创建适当的副本。然后按照您正确指定的方式编写容器的深层副本。
编辑:我的工作假设是,你的大一学生等是从学生的下降。如果不是,请使用变体<>并应用副本访问者。
这是一个很好的示例https://*.com/questions/5148706/copying-a-polymorphic-object-in-c –
谢谢!这正是我所需要的。 –
解决所有权问题
如果你认为你的模块之间共享的Student
-s,那么你面临的所有权问题,我会建议使用的std::shared_ptr<Student>
-s矢量来解决它。
如果你有std::vector<std::shared_ptr<Student>>
,你可以将它传递给你想要的任何人。接收者可以使用赋值运算符复制vector
,稍后他添加/删除的任何对象都不会影响原始容器,就像您似乎期望的那样。
解决问题克隆
如果您有兴趣每个模块有自己的一个Student
的副本-s载体,你所面临的克隆问题。
您可以通过添加下面的方法到类解决这个问题:
class Student {
[..]
virtual Student * clone() const = 0; // Assuming Student is abstract, otherwise implement as well
};
class Freshman : public Student {
[..]
virtual Freshman * clone() const { return new Freshman(*this); }
};
// Same for other derived classes...
,然后使用std::transform
复制的载体:
// students is the original std::vector<Student *>
std::vector<Student *> copy(students.size());
std::transform(students.begin(), students.end(), copy.begin(), [](Student * s) -> Student * { return s->clone(); });
顺便说一句,这是大二,不Sophmore .. 。
我不认为这是OP想要的。当我相信OP需要深度复制时,使用'std :: shared_ptr'会给你一个浅的副本。 – NathanOliver
根据OP的说法,@NathanOliver说:“因为那只会复制指针地址,所以如果外部的人删除了这些指针指向的对象,那么StudentService类就会因此而受到影响。”这绝对可以防止它。 –
是的,它使它安全,但现在这两个向量仍然指向同一个对象。我相信OP希望两个矢量都有自己指向的对象。 – NathanOliver
忘记载体。你将如何从'Student'指针创建一个'Freshman'?这是您需要在SO上搜索的问题。 – juanchopanza
http://www.boost.org/doc/libs/1_65_1/doc/html/poly_collection.html –
由于学生在不同的地方被“使用”,学生是否在你的大学克隆? – 2017-10-10 15:39:38