如何使用CRTP和多重继承C ++转发构造函数

时间:2019-04-21 18:42:15

标签: c++11 inheritance constructor forward crtp

我最近正在研究使用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中那样使用带有包扩展的声明。

0 个答案:

没有答案