仅使用基类指针复制派生实体(无需彻底测试!) - C ++ [英] Copying derived entities using only base class pointers, (without exhaustive testing!) - C++

查看:138
本文介绍了仅使用基类指针复制派生实体(无需彻底测试!) - C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个由多个派生类继承的基类,以及一个需要通过基类指向每个实体来管理这些基类的程序结构。是否有一个简单的方法来复制整个派生对象,只有基类指针已知?



看看周围它似乎可能(如果令人难以置信的繁琐)使用 dynamic_cast 调用以检查是否可以将基指针转换为适当的派生类,然后使用派生类的复制构造函数复制它。然而,这不是一个真正的最佳解决方案,部分是由于过度使用dynamic_cast,也会看到一个令人头痛的维护和扩展。



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

  class Base 
{
public:
Base基地&其他);
virtual Base * getCopy();
...
}

类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()在Base类指针上的任何派生对象仍然得到一个基类指针回来,但是整个派生对象已经被复制。这个方法感觉更容易维护,因为它只需要在所有派生类中使用类似的 getCopy()函数,并且不需要测试所有可能的派生对象。



这本质上是明智的吗?

解决方案

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



对你的实际代码有两个意见。首先,C ++继承允许一个派生类重写一个基类成员函数,让派生函数返回一个比基类版本更具体的类型的指针。这称为协方差。作为示例,如果基类函数是

  virtual Base * clone()const;一个派生类可以覆盖它




  virtual Derived * clone()const; 

这将工作完美。例如,这样可以有如下代码:

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

其中,没有协变过载,将不合法。



另一个细节 - 在代码中,你显式地 static_cast 指向代码中的基本指针的派生指针。这是完全合法的,但它没有必要。 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?

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));
}

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.

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.

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.

这篇关于仅使用基类指针复制派生实体(无需彻底测试!) - C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆