【问题标题】:Copy a derived class with only a base class pointer in C++在 C++ 中复制仅具有基类指针的派生类
【发布时间】:2020-02-27 17:17:43
【问题描述】:

我正在尝试仅使用基类指针制作派生类的副本。

如果我有:

class BaseClass; //Abstract class with =0 functions
class LeftClass : BaseClass;
class RightClass : BaseClass;

我有一个以 BaseClass 作为参数的函数:

void Function(BaseClass* baseClass)

我想复制 BaseClass,但我也想复制 LeftClass 的扩展功能 OR RightClass,但我不知道将哪个传递给函数 - 两者都可以.

所以我有这样的事情:

//global
vector<BaseClass*> myVector;

void Function(BaseClass* baseClass)
{
   BaseClass* baseClassCopy = new BaseClass(baseClass);
   myVector.push_back(baseClassCopy);
}   

然后我用左或右类调用函数

int main()
{
   LeftClass leftClass;
   Function(&leftClass);
   LeftClass* ResultOfCopy = myVector.at(0);
}

该代码不会复制整个 leftclass 作为副本,有没有办法做到这一点我忽略了?

另外BaseClass 是抽象的,其中一些功能是=0,所以我不能新建一个。否则在其他类中有复制功能可以使用。

【问题讨论】:

  • 看起来你需要clone functionality
  • 有没有办法在不修改任何类的情况下做到这一点?我是单元测试,所以我不应该更改任何代码...
  • 哦,等等,我可能有一个解决方案。谢谢! :)
  • 等等,如果 BaseClass 是抽象的,我不能“新建”一个新的呢?
  • @Sam 即使可以,它也会new 错误的课程。您从根本上需要向您的类添加一个clone 方法(“虚拟复制构造函数”)以获得此功能,而不是像Nathan 的回答那样作弊(但实际上,不要那样做)。

标签: c++ inheritance copy


【解决方案1】:

如果您无法更改任何类以添加克隆函数,那么您可以自己手动执行此操作,方法是使用dynamic_cast 确定其运行时类型并调用正确的派生构造函数。看起来像

void Function(BaseClass* baseClass)
{
    if (auto ptr = dynamic_cast<LeftClass*>(baseClass))
        myVector.push_back(new LeftClass(*ptr));
    if (auto ptr = dynamic_cast<RightClass*>(baseClass))
        myVector.push_back(new RightClass(*ptr)); 
}  

你可以看到它在这个live example中工作

【讨论】:

  • 知道了,谢谢。不过,对于 SO 来说,我还不能投票支持 cmets 或解决方案。 :)
  • @Sam 不用担心。很高兴能提供帮助。
【解决方案2】:

这类问题一般通过clone()方法解决。

class BaseClass
{
    virtual BaseClass* clone()            = 0
};

class LeftClass: public BaseClass
{
    virtual LeftClass* clone() override {return new LeftClass(*this);}
};
class RightClass: public BaseClass
{
    virtual RightClass* clone() override {return new RightClass(*this);}
};
class RightRightClass: public RightClass
{
    virtual RightRightClass* clone() override {return new RightRightClass(*this);}
};

您的函数现在很容易编写:

void Function(BaseClass* baseClass)
{
   BaseClass* baseClassCopy = !baseClass ? nullptr : baseClass->clone();
   myVector.push_back(baseClassCopy);
}   

【讨论】:

  • 这仍然会创建一个BaseClass 类型的对象,这并不能解决“复制LeftClass 或RightClass 的功能”的问题
  • @TheGoldKnight23 不。这将创建一个正确类型的对象,但返回一个指向正确类型对象的BaseClass 指针。注意对new 的调用:return new LeftClass(*this);return new RightClass(*this);
  • 但是您将无法通过该指针访问LeftClassRightClass 的功能,尽管我明白您的观点,即技术上它确实会复制它并返回正确的对象(这就是 dynamic_cast 起作用的原因)
  • @TheGoldKnight23 是的,你会的!注意:BaseClass 是一个虚拟基类。您要访问的函数是在派生类中被覆盖的虚拟方法。所以你可以完全访问这些。
  • 对,对不起,虽然他们的意思是访问成员没有在BaseClass 中声明。是的,当然可以,但是当您可以使用编译时成本的模板时,为什么还要使用 dynamic_cast 和运行时成本?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 2013-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多