【问题标题】:Implementing Clone() method in base class在基类中实现 Clone() 方法
【发布时间】:2010-10-27 07:25:37
【问题描述】:

这是我班级的Clone() 实现:

    MyClass^ Clone(){
        return gcnew MyClass(this->member1, this->member2);
    }

现在我有大约 10 个从 MyClass 派生的类。每种情况下的实现都是相同的。由于在每种情况下我都需要用实际的类名调用gcnew,因此我需要创建10 个几乎相同的Clone() 实现。

有没有办法在基类中编写一个单一的Clone() 方法来服务所有 10 个派生类?

编辑: 有没有办法通过其中一个对象调用类的构造函数?以某种方式调用实际的派生类构造函数。比如:

MyClass ^obj2 = obj1->Class->Construct(arg1, arg2);

我在 C++/CLI 上执行此操作,但欢迎使用其他语言的答案。

【问题讨论】:

    标签: oop constructor clone platform-agnostic


    【解决方案1】:

    在普通的旧 C++ 中,您可以使用编译时多态性(奇怪重复的模板模式)来做到这一点。假设你的派生类是可复制的,你可以写:

    
    class Base
    {
    public:
        virtual Base* Clone() const = 0;
    //etc.
    };
    template <typename Derived>
    class BaseHelper: public Base
    {
        //other base code here
    
        //This is a covariant return type, allowed in standard C++
        Derived * Clone() const
        {
             return new Derived(static_cast<Derived *>(*this));
        }
    };
    

    然后像这样使用它:

    
    class MyClass: public BaseHelper<MyClass>
    {
        //MyClass automatically gets a Clone method with the right signature
    };
    

    请注意,您不能再次从一个类派生并让它无缝工作 - 您必须通过模板化中间类来“设计”再次派生的选项,或者重新开始重写Clone

    【讨论】:

      【解决方案2】:

      不是我知道的 C++。正如您所说,您需要在 Clone() 的每个实现中创建不同类的对象。

      【讨论】:

        【解决方案3】:

        嗯,我想你可以在这里使用工厂模式。即:

        MyClass Clone(){
            return MyClassFactory.createInstance(this.getClass(), this.member1, this.member2, ...);
        }
        

        在工厂中,您必须根据传递的类类型创建子类的实例。因此,它可能与您的方法具有相同的缺点。

        【讨论】:

          【解决方案4】:

          我建议改用复制构造函数(因为派生类也可以调用基实现的复制构造函数)——这也很方便,因为它是 C++ 程序员熟悉的领域。

          您也许可以创建一个使用反射在此实例中调用自身的复制构造函数的单个 Clone 方法。

          可能还值得注意的是,Jeffrey Richter 在《框架设计指南》一书中说,“ICloneable 接口是一个非常简单的抽象示例,其中包含从未明确记录过的契约。某些类型实现了此接口的 Clone 方法,因此它执行对象的浅拷贝,而某些实现执行深拷贝。因为这个接口的Clone 方法应该做的事情从未完全记录,当使用具有实现ICloneable 的类型的对象时,你永远不知道你在做什么'会得到。这使得界面无用“(强调我的)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-08-26
            • 1970-01-01
            • 2012-07-06
            • 1970-01-01
            • 1970-01-01
            • 2017-06-07
            • 1970-01-01
            相关资源
            最近更新 更多