【问题标题】:Can a copy constructor be defined in the base class and still handle derived class circumstances?可以在基类中定义复制构造函数并仍然处理派生类的情况吗?
【发布时间】:2019-12-19 18:17:45
【问题描述】:

我的类结构如下:

class P {
    public:
        virtual std::auto_ptr<P> clone() const=0;
};

class A : public P {
    public:
        std::auto_ptr<P> clone() const {
            return std::auto_ptr<P>(new A(*this));
        }
};

class B : public P {
    public:
        std::auto_ptr<P> clone() const {
            return std::auto_ptr<P>(new B(*this));
        }
};

class C : public P {
    public:
        std::auto_ptr<P> clone() const {
            return std::auto_ptr<P>(new C(*this));
        }
};

这只是复制构造函数的代码:ABC 类都有不同的代码,否则。这里代码重复很多,能不能简化一下?

【问题讨论】:

  • 旁注:请记住 std::auto_ptr 在 C++11 中已被弃用并在 C++17 中被删除
  • @AdamStepniak 我知道,我仅限于标签中定义的 C++03 约束。
  • 回复:“这只是复制构造函数的代码”——不,这里没有用户定义的复制构造函数。 clone() 不是复制构造函数。但是每个clone() 函数都使用它的类的复制构造函数。

标签: c++ copy virtual c++03


【解决方案1】:

使用 CRTP,您可以这样做:

template <typename Derived, typename Base>
struct Clonable : public Base
{
    std::auto_ptr<Base> clone() const {
        return std::auto_ptr<Base>(new Derived(static_cast<const Derived&>(*this)));
    }
};

class A : public Clonable<A, P> {}; 
class B : public Clonable<B, P> {}; 
class C : public Clonable<C, P> {}; 

为了让派生类受益于真实类型,我会将代码修改为:

class P {
public:
    std::auto_ptr<P> clone() const { return std::auto_ptr<P>(vclone()); }
private:
    virtual P* vclone() const = 0;
};

template <typename Derived, typename Base>
struct Clonable : public Base
{
    std::unique_ptr<Derived> clone() const {
        return std::unique_ptr<Derived>(static_cast<Derived*>(vclone()));
    }
private:
    // Cannot use covariant-type `Derived*` in CRTP as Derived is not complete yet
    Base* vclone() const {
        return new Derived(static_cast<const Derived&>(*this));
    }
};

class A : public Clonable<A, P> {}; 
class B : public Clonable<B, P> {}; 
class C : public Clonable<C, P> {}; 

所以,以下是有效的:

A a;
std::auto_ptr<A> a_copy =  a.clone();

【讨论】:

    【解决方案2】:

    是否可以在基类中定义复制构造函数并仍然处理派生类的情况?

    一般来说,简短的回答是“否”。

    如果编译器生成的复制构造函数足够的话,它就可以正常工作。

    如果定义派生类时编译器生成的复制构造函数不够用,则无法绕过在派生类中定义的需要。

    【讨论】:

      【解决方案3】:

      如果您的意思是,是否有一种方法可以为每个派生类提供一个克隆方法而无需显式写出:答案是否定的。如果将元类添加到 C++ 中,这将成为可能,但不要指望它会在一段时间内成为语言。

      但是,Boost.Any 可以在不知道动态类型的情况下复制对象,并且可以在 C++03 中实现。如果您愿意,可以使用类似类型的擦除技术。简而言之,这将包括:

      • 具有虚拟 clone 方法和虚拟析构函数的 ClonablePBase
      • 派生自ClonablePBaseClonableP 类模板。 ClonableP&lt;T&gt; 类型的对象(其中T 派生自P)拥有一个T 对象,并且知道如何使用T 的复制构造函数来克隆自己。
      • 拥有std::auto_ptr&lt;ClonablePBase&gt;AnyP 类。它通过调用虚拟克隆方法来复制自己。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-24
        • 2017-10-31
        • 2020-04-23
        • 1970-01-01
        • 2012-03-11
        • 2013-06-23
        • 1970-01-01
        相关资源
        最近更新 更多