仅使用基类指针复制派生实体,(无需详尽测试!)- C++

给定一个由大量派生类继承的基类,以及一个需要您通过指向每个实体的基类指针来管理这些派生类的程序结构.当只知道基类指针时,有没有一种简单的方法可以复制整个派生对象?

Given a base class that is inherited by plethora of derived classes, and a program structure that requires you manage these via base class pointers to each entity. Is there a simple way to copy the entire derived object when only the base class pointer is known?

环顾四周,使用 dynamic_cast 调用来检查是否可以将基指针转换为适当的派生类,然后使用派生类的复制构造函数复制它似乎是可能的(如果非常乏味的话).然而,这并不是一个真正的最佳解决方案,部分原因是过度使用了 dynamic_cast,而且维护和扩展会让人头疼.

Looking around it would seem possible (if incredibly tedious) to use the dynamic_cast call to check if a base pointer can be cast as the appropriate derived class, then copy it using the derived class's copy constructor. However this is not really an optimal solution partly due to the excessive use of dynamic_cast and also it would see a total headache to maintain and extend.

我遇到的另一个更优雅的解决方案如下:

Another more elegant solution I have come across is as follows:

class Base
{
public:
   Base(const Base& other);
   virtual Base* getCopy();
   ...
}

class Derived :public Base
{
   Derived(const Derived& other);
   virtual Base* getCopy();
   ...
}

Base* Base::getCopy()
{
   return new Base(*this));
}

Base* Derived::getCopy()
{
   return static_cast<Base*>(new Derived(*this));
}

然后通过在指向任何派生对象的基类指针上调用 getCopy(),仍然会返回一个基类指针,但整个派生对象也已被复制.这种方法感觉更易于维护,因为它只需要在所有派生类中都有一个类似的 getCopy() 函数,并且不需要针对所有可能的派生对象进行测试.

Then by calling getCopy() on the Base class pointer to any derived object one still gets a base class pointer back but also the whole of the derived object has been copied. This method feels a lot more maintainable as it just requires a similar getCopy() function to be in all derived classes, and does away with the need to test against all possible derived objects.

本质上,这是明智的吗?或者有没有更好、更简洁的方法来做到这一点?

Essentially, is this wise? or is there a better, even neater way of doing this?

推荐答案

这种方法是复制多态对象的首选方法,因为它减轻了确定如何将任意类型的对象复制到该对象的责任,而不是尝试在编译时确定它.更一般地说,如果您不知道基类指针在编译时指向什么,您就不可能知道需要执行许多潜在代码段中的哪一个才能获得正确的副本.正因为如此,任何可行的解决方案都需要动态选择代码,而虚函数是一个很好的方法.

This approach is the preferred way of copying polymorphic objects because it offloads the responsibility of determining how to copy an object of an arbitrary type to that object, rather than trying to determine it at compile-time. More generally, if you don't know what the base class pointer points at at compile-time, you can't possibly know which of the many potential pieces of code you would need to execute in order to get a correct copy. Because of this, any working solution will need a dynamic selection of code, and the virtual function is a good way to do this.

对您的实际代码的两条评论.首先,C++ 继承允许派生类覆盖基类成员函数,使派生函数返回一个类型比基类版本更具体的指针.这称为协方差.例如,如果基类函数是

Two comments on your actual code. First, C++ inheritance allows a derived class overriding a base class member function to have the derived function return a pointer of a type more specific than the base class version. This is called covariance. As an example, if a base class function is

virtual Base* clone() const;

然后派生类可以将其覆盖为

Then a derived class can override it as

virtual Derived* clone() const;

这将工作得很好.例如,这允许您拥有这样的代码:

And this will work perfectly fine. This allows you, for example, to have code like this:

Derived* d = // something...
Derived* copy = d->clone();

如果没有协变重载,就不合法.

Which, without the covariant overload, wouldn't be legal.

另一个细节 - 在您拥有的代码中,您明确地static_cast 派生指针指向代码中的基指针.这是完全合法的,但没有必要.C++ 将派生类指针隐式转换为基类指针,无需强制转换.但是,如果您使用协变返回类型的想法,则不会出现这种情况,因为返回类型将与您将创建的对象的类型相匹配.

Another detail - in the code you have, you explicitly static_cast the derived pointers to base pointers in your code. This is perfectly legal, but it's not necessary. C++ will implicitly convert derived class pointers to base class pointers without a cast. If, however, you use the covariant return type idea, this won't come up because the return type will match the type of the objects you'll be creating.

相关文章