从指向基类的指针调用派生类的复制构造?

Posted

技术标签:

【中文标题】从指向基类的指针调用派生类的复制构造?【英文标题】:Invoke the copy construction of a derived class from a pointer to the base class? 【发布时间】:2015-06-01 01:29:05 【问题描述】:

我有

1- class A int m;;
2- class B: public A
float n;;
3- class C: public A
string n;;

我将A类的所有实例都存储在

vector <class A*> myInstansesofA;

它被存储为一个指针,因为我根据一些 if 语句动态创建它们

if (some condition)

      A* newA = new B();
      myInstancesofA.push_back(newA );

else

      A* newA = new C();
      myInstancesofA.push_back(newA );

现在我需要创建矢量的精确副本。使用新的指针集,但数据的精确副本。

问题在于将 A 的每个实例(实际上是 B 和 C)的数据复制到新向量。

我尝试了以下方法,但它不起作用。

for (vector<A*>::const_iterator it = myInstancesofA.begin(); it != myInstancesofA.end(); ++it)
    
        A* newA = new A(*(*it));
        myInstancesofA.push_back(newA );
    

我怀疑发生此错误是因为“new A”仅调用类型 A 的复制构造函数,而不调用 B 或 C(我调试并发现这种情况正在发生)。

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

我相信你不能像那样调用构造函数,并且在 C++ 中没有直接的方法来做类似的事情(对于像 Java 和 C# 这样的反射语言来说,这是非常简单的)。

一种方法是使用prototype pattern

class A 
public:
    virtual A* clone() 
        return new A ...;
    
;

class B : public A 
public:
    A* clone() override 
        return new B .........;
    
;

class C : public A 
public:
    A* clone() override 
        return new C .........;
    
;

对象本身负责创建自己的克隆。当然在设计上还有很多需要改进的地方,但至少它能让你体验一下。

【讨论】:

好线索,但有一些小细节:BC 应该从A 派生,并且new B()new B 慢(它需要在之前执行零初始化默认构造) - 没有理由在这里使用它;理想情况下,OP会添加构造函数来设置任何必要的字段并简化为例如return new B(...args...);。最后,对于B::cloneC::clone,最好使用override 而不是virtual @TonyD Gosh 我无法想象我错过了那些明显的东西,修复它们(我想我需要一些咖啡):P for new B() 我不知道你提到的差异,可以导致我要一些资料吗? (对不起,我知道的话题:P) 我也需要一杯咖啡!无论如何,在 C++11 标准 4.3.4/17 中要求“如果省略 new-initializer,则默认初始化对象(8.5);如果不执行初始化,则对象具有不确定的值。——否则, new-initializer 根据 8.5 的初始化规则进行解释,用于直接初始化。”,在 8.5/11 和 /17 下,() 不带参数意味着“值已初始化”,在 8.5/8 中进行了描述,如果存在则首先指定零初始化编译器提供的默认构造函数。

以上是关于从指向基类的指针调用派生类的复制构造?的主要内容,如果未能解决你的问题,请参考以下文章

为啥指向基类的派生类指针可以调用派生类成员函数? [复制]

如何从指向多态基类的指针复制/创建派生类实例?

在 C++ 继承中,当指向基类的指针对象指向派生类时,不调用派生类析构函数

关于C++基类、派生类的引用和指针

如果继承类型受到保护,我可以使基类的指针指向派生对象吗? [复制]

虚函数和基类中的this指针的问题!