我正在使用CRTP向继承的类添加克隆方法,例如: class Base { virtual ~Base() {}; virtual Base* clone() const = 0;}; templateclass Derived class BaseCopyable : Base{ public: virtual Base* clone() const { return new Derived(sta
class Base { virtual ~Base() {}; virtual Base* clone() const = 0; }; template<class Derived> class BaseCopyable : Base { public: virtual Base* clone() const { return new Derived(static_cast<Derived const&>(*this)); } }; class A : public BaseCopyable<A>; class B : public BaseCopyable<B>; etc...
但是如果我有一个继承自B的类,例如:
class differentB : public B;
然后clone()不返回类型为differentB的对象,它返回一个B.除了在differentB中编写一个新的clone()方法,有没有办法解决这个问题?
谢谢阅读!
这是我对 this question的回答的返工您的意图是在层次结构中包含所有派生类
从它们的基类继承可克隆性(多态复制)
你不需要为每个人提供覆盖
clone(),但您尝试使用类模板的CRTP解决方案
BaseCopyable只能以这种方式赋予可克隆性
类立即派生自Base,而不是派生类
来自这样的派生类.
我认为不可能向下传播可克隆性
通过赋予“只有一次”的克隆性来任意深层次
最顶尖的具体课程.你必须在每个上明确赋予它
具体的类,但你可以通过他们的基类和
不使用CRTP重复覆盖clone()
将可克隆性从父类传递到子类的模板
层次结构.
显然,符合此法案的CRTP模板与BaseCopyable不同
通过要求两个模板参数:父类型和子类型.
C 03解决方案如以下程序所示:
#include <iostream> // As base of D, this makes D inherit B and makes D cloneable to // a polymorphic pointer to B template<class B, class D> struct cloner : virtual B { virtual B *clone() const { return new D(dynamic_cast<D const&>(*this)); } virtual ~cloner() {} }; struct Base { virtual ~Base() { std::cout << "I was a Base" << std::endl; }; virtual Base* clone() const = 0; }; struct A : cloner<Base,A> // A inherits Base { virtual ~A() { std::cout << "I was an A" << std::endl; }; }; struct B : cloner<Base,B> // B inherits Base { virtual ~B() { std::cout << "I was a B" << std::endl; }; }; struct DB : cloner<B,DB> // DB inherits B, Base { virtual ~DB() { std::cout << "I was a DB" << std::endl; }; }; int main() { Base * pBaseA = new A; Base * pBaseB = new B; Base * pBaseDB = new DB; Base * pBaseCloneOfA = pBaseA->clone(); Base * pBaseCloneOfB = pBaseB->clone(); Base *pBaseCloneOfDB = pBaseDB->clone(); B * pBCloneOfDB = dynamic_cast<B*>(pBaseDB->clone()); std::cout << "deleting pBaseA" << std::endl; delete pBaseA; std::cout << "deleting pBaseB" << std::endl; delete pBaseB; std::cout << "deleting pBaseDB" << std::endl; delete pBaseDB; std::cout << "deleting pBaseCloneOfA" << std::endl; delete pBaseCloneOfA; std::cout << "deleting pBaseCloneOfB" << std::endl; delete pBaseCloneOfB; std::cout << "deleting pBaseCloneOfDB" << std::endl; delete pBaseCloneOfDB; std::cout << "deleting pBCloneOfDB" << std::endl; delete pBCloneOfDB; return 0; }
输出是:
deleting pBaseA I was an A I was a Base deleting pBaseB I was a B I was a Base deleting pBaseDB I was a DB I was a B I was a Base deleting pBaseCloneOfA I was an A I was a Base deleting pBaseCloneOfB I was a B I was a Base deleting pBaseCloneOfDB I was a DB I was a B I was a Base deleting pBCloneOfDB I was a DB I was a B I was a Base
前提是所涉及的所有类都是默认可构造的,B
不必是克隆人的虚拟基础< B,D>你可以删除虚拟
struct cloner中的关键字:virtual B.否则,B必须是虚拟基础
这样B的非默认构造函数可以由D的构造函数调用,
虽然B不是D的直接基础.
在C 11中,我们有可变参数模板,您可以不使用虚拟模板
通过提供克隆人< B,D>完全继承.用“多用途”
模板构造函数,它可以通过它转发任意构造函数
从D到B的参数.以下是对此的说明:
#include <iostream> template<class B, class D> struct cloner : B { B *clone() const override { return new D(dynamic_cast<D const&>(*this)); } ~cloner() override {} // "All purpose constructor" template<typename... Args> explicit cloner(Args... args) : B(args...){} }; struct Base { explicit Base(int i) : _i(i){} virtual ~Base() { std::cout << "I was a Base storing " << _i << std::endl; }; virtual Base* clone() const = 0; protected: int _i; }; struct A : cloner<Base,A> { explicit A(int i) : cloner<Base,A>(i){} ~A() override { std::cout << "I was an A storing " << _i << std::endl; }; }; struct B : cloner<Base,B> { explicit B(int i) : cloner<Base,B>(i){} ~B() override { std::cout << "I was a B storing " << _i << std::endl; }; }; struct DB : cloner<B,DB> { explicit DB(int i) : cloner<B,DB>(i){} ~DB() override { std::cout << "I was a DB storing " << _i << std::endl; }; }; int main() { Base * pBaseA = new A(1); Base * pBaseB = new B(2); Base * pBaseDB = new DB(3); Base * pBaseCloneOfA = pBaseA->clone(); Base * pBaseCloneOfB = pBaseB->clone(); Base * pBaseCloneOfDB = pBaseDB->clone(); B * pBCloneOfDB = dynamic_cast<B*>(pBaseDB->clone()); std::cout << "deleting pA" << std::endl; delete pBaseA; std::cout << "deleting pB" << std::endl; delete pBaseB; std::cout << "deleting pDB" << std::endl; delete pBaseDB; std::cout << "deleting pBaseCloneOfA" << std::endl; delete pBaseCloneOfA; std::cout << "deleting pBaseCloneOfB" << std::endl; delete pBaseCloneOfB; std::cout << "deleting pBaseCloneOfDB" << std::endl; delete pBaseCloneOfDB; std::cout << "deleting pBCloneOfDB" << std::endl; delete pBCloneOfDB; return 0; }
输出是:
deleting pA I was an A storing 1 I was a Base storing 1 deleting pB I was a B storing 2 I was a Base storing 2 deleting pDB I was a DB storing 3 I was a B storing 3 I was a Base storing 3 deleting pBaseCloneOfA I was an A storing 1 I was a Base storing 1 deleting pBaseCloneOfB I was a B storing 2 I was a Base storing 2 deleting pBaseCloneOfDB I was a DB storing 3 I was a B storing 3 I was a Base storing 3 deleting pBCloneOfDB I was a DB storing 3 I was a B storing 3 I was a Base storing 3