我最近正在研究使用crtp在c ++ 11中使用协方差来克隆对象,我发现了这一点:https://www.fluentcpp.com/2017/09/12/how-to-return-a-smart-pointer-and-use-covariance/ 该帖子很明确,并且在某种程度上有效。帖子没有说的是如何在构造函数中使用参数。我使用Base :: Base获得了虚拟技巧,尽管它强制用户在实例化叶子类时显式调用基本构造函数。仅当您要搜索诸如钻石继承之类的内容时,才需要这样做。
但是,在更常见的情况下,当您具有多个继承级别时,将具有以下内容: 抽象A->抽象B->抽象C->具体D。 我明白为什么只有叶子类应该是可实例化的。但是在每个级别,构造函数都越来越具体,以我链接的CRTP设计示例为例,我不知道该怎么做。
此后,我想出了只具有一个基类的简化方法:
// Virtual and abstract tricks
template <typename Base>
class Virtual : virtual public Base
{
public:
using Base::Base;
};
template <typename Object>
class Abstract
{
};
// General CRTP : Inheritance + implementation of clone function
template <typename Object, typename Base=void>
class Clone : public Base
{
public:
virtual ~Clone() =default;
std::unique_ptr<Object> clone() const {
return std::unique_ptr<Object>(static_cast<Object *>(this->copy()));
}
private:
virtual Clone * copy() const override {
return new Object(static_cast<const Object &>(*this));
}
};
// Specialization : Inheritance + an pure cloning function
template <typename Object>
class Clone<Abstract<Object>>
{
public:
virtual ~Clone() =default;
std::unique_ptr<Object> clone() const {
return std::unique_ptr<Object>(static_cast<Object *>(this->copy()));
}
private:
virtual Clone *copy() const =0;
};
关于我的考试班:
class TestB0 : public Clone<Abstract<TestB0>>
{
public:
TestB0() : B0(new int(0)) {cout<<"crea B0 vide"<<endl;}
TestB0(int xB0) : B0(new int(xB0)) {cout<<"crea B0 "<<xB0<<" : "<<*B0<<endl;}
TestB0(const TestB0 &t) : B0(new int(*t.B0)) {cout<<"copy B0 "<<*B0<<endl;}
virtual ~TestB0() {delete B0;}
void setB0(int xB0) {*B0=xB0;}
int getB0() {return *B0;}
private:
int *B0;
};
class TestB1 : public Clone<TestB1, TestB0>
{
public:
TestB1() : B1(new int(0)) {cout<<"crea B1 vide"<<endl;}
TestB1(int xB0=11, int xB1=20) : B1(new int(xB1)) {cout<<"crea B1 "<<xB0<<" "<<xB1<<" : "<<getB0()<<" "<<*B1<<endl;}
TestB1(const TestB1 &t) : B1(new int(*t.B1)) {cout<<"copy B1 "<<getB0()<<" "<<*B1<<endl;}
virtual ~TestB1() {delete B1;}
void setB1(int xB1) {*B1=xB1;}
int getB1() {return *B1;}
private:
int *B1;
};
当我实例化TestB1时,我无权访问TestB0的构造函数。 我可以使用虚拟技巧来做到这一点:
class TestB1 : public Clone<TestB1, Virtual<TestB0>>
但是,当我这样做时,我必须在叶子类中显式调用构造函数。当我只有一个继承级别时,这不是问题。我想这是我有更多的时候。
我无法找到一种使整个过程优雅运行的方法。 有没有一种方法可以在不使用虚拟基类的情况下初始化基类?以通常在不使用CRTP的情况下完成的方式。
谢谢你的帮助。
作为评论:我正在为我要从时间执行角度(因此没有虚拟表)优化的库创建多态类。我只能与c ++ 11一起工作,因此不能像在c ++ 17中那样使用带有包扩展的声明。