我很长一段时间一直在努力解决这类问题,所以我决定在这里问一下.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
Run Code Online (Sandbox Code Playgroud)
该方法应返回动态创建的副本,或者至少将对象存储在某些数据结构中的堆栈上以避免"返回临时地址"问题.
实现上述方法的天真方法是在一系列if语句中使用多个typeids或dynamic_casts来检查每个可能的派生类型,然后使用new运算符.还有其他更好的方法吗?
PS:我知道,使用智能指针可以避免这个问题,但我对简约方法感兴趣,没有一堆库.
有几次我偶然发现了我有一个需要复制的指针容器的场景.
假设我们有以下类层次结构:
学生(基础班)
StudentService
StudentService类有一个std::vector<Student*> students字段和以下构造函数:
StudentService::StudentService(std::vector<Student*> students) {
// code
}
Run Code Online (Sandbox Code Playgroud)
仅使用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));
}
Run Code Online (Sandbox Code Playgroud)
但即使这样也不合适,因为它会创建ONLY Student对象.我们知道学生可以是新生,索菲尔,初中或高级.所以这是我的问题:这个问题的最佳解决方案是什么?
我想有一种方法是在每个Student类中放置一个私有枚举字段,并有4个if-else语句检查它是什么类型的Student,然后根据它创建一个新的动态对象:
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... …Run Code Online (Sandbox Code Playgroud) 好的,还有一些代码.
#include <iostream>
#include <deque>
using namespace std;
class A
{
public:
virtual void Execute()
{
cout << "Hello from class A" << endl;
}
};
class B: public A
{
public:
void Execute()
{
cout << "Hello from class B" << endl;
}
};
void Main()
{
deque<A *> aclasses = deque<A*>(0);
deque<A *> aclasses2 = deque<A*>(0);
A a1 = A();
B b1 = B();
aclasses.push_back(&a1);
aclasses.push_back(&b1);
aclasses[0]->Execute();
aclasses[1]->Execute();
//Now say I want to copy a class from aclasses …Run Code Online (Sandbox Code Playgroud) #include<iostream>
using namespace std;
class Something
{
public:
int j;
Something():j(20) {cout<<"Something initialized. j="<<j<<endl;}
};
class Base
{
private:
Base(const Base&) {}
public:
Base() {}
virtual Base *clone() { return new Base(*this); }
virtual void ID() { cout<<"BASE"<<endl; }
};
class Derived : public Base
{
private:
int id;
Something *s;
Derived(const Derived&) {}
public:
Derived():id(10) {cout<<"Called constructor and allocated id"<<endl;s=new Something();}
~Derived() {delete s;}
virtual Base *clone() { return new Derived(*this); }
virtual void ID() { cout<<"DERIVED id="<<id<<endl; } …Run Code Online (Sandbox Code Playgroud) c++ ×4
arrays ×1
class ×1
containers ×1
copy ×1
deep-copy ×1
inheritance ×1
instance ×1
pointers ×1
polymorphism ×1
shallow-copy ×1
virtual ×1