Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 结合虚拟继承使用CRTP_C++_Crtp_Virtual Inheritance - Fatal编程技术网

C++ 结合虚拟继承使用CRTP

C++ 结合虚拟继承使用CRTP,c++,crtp,virtual-inheritance,C++,Crtp,Virtual Inheritance,我有一个节点层次结构,其中可以出现“菱形” 每个节点都必须是可克隆的,但我不想将克隆方法写入每个节点。所以我使用CRTP class Node { public: Node(){} Node(Fill*) { } virtual ~Node() {} virtual Node * clone() const = 0; virtual void id() { std::cout << "Node\n"; } }; //===========

我有一个节点层次结构,其中可以出现“菱形”

每个节点都必须是可克隆的,但我不想将克隆方法写入每个节点。所以我使用CRTP

class Node
{
public:
    Node(){}
    Node(Fill*) { }

    virtual ~Node() {}
    virtual Node * clone() const = 0;

    virtual void id() { std::cout << "Node\n"; }
};

//====================================================================

template <typename Base, typename Derived>
class NodeWrap : public Base
{
public:

    NodeWrap() { } 
    NodeWrap(Fill * arg1) : Base(arg1) { }

    virtual Node *clone() const
    {
        return new Derived(static_cast<Derived const &>(*this));
    }
};
现在正在建造钻石结构:

class NodeB : public NodeWrapVirtual<Node, NodeB>
{
public:
typedef NodeWrapVirtual<Node, NodeB> BaseClass;

NodeB() { }
NodeB(Fill * f) : BaseClass(f) { }

virtual void id() { std::cout << "NodeB\n"; }
};

//====================================================================

class NodeC : public NodeWrapVirtual<Node, NodeC>
{
public:
    typedef NodeWrapVirtual<Node, NodeC> BaseClass;

    using BaseClass::clone;

    NodeC() { }
    NodeC(Fill * f) : BaseClass(f) { }

    virtual void id() { std::cout << "NodeC\n"; }
};
class节点B:公共节点wrapvirtual
{
公众:
typedef NodeWrapVirtual基类;
NodeB(){}
NodeB(Fill*f):基类(f){}

virtual void id(){std::cout每个虚拟函数在每个派生类中都必须有一个唯一的最终重写器。这与名称查找无关(要求的是函数,而不是它们的名称),因此使用
与此无关

使用多基类节点类模板:

 template <class Derived, class Base1, class Base2>
 class node2 : //  etc
 // or use a variadic template if you have more than two bases
模板
类node2://etc
//或者,如果有两个以上的碱基,则使用可变模板

至于协变返回,如果方便的话,它们是完全不必要的。您可以始终将每个虚拟函数分为私有虚拟函数和公共非虚拟函数。如果您想返回协变智能指针,这很方便,因为常规协变返回机根本不支持协变智能指针。

首先,您应该非常小心地使用它对虚拟基中的成员使用虚拟继承(请参阅“有效的C++”,第20项:“避免公共接口中的数据成员”和)。您的
节点
获取一个指向未使用的
填充
的指针,但看起来您需要它

当您移动
节点包裹
基类中的固有关系(
public virtual
public
)时,您的问题就可以解决了

template <typename Base>
class  InheritVirtual
    : public virtual Base
{};

template <typename... Bases>
class InheritBases
    : public Bases...
{
    virtual Node* clone() const = 0;
    virtual void id() const = 0;
};

class NodeB : public NodeWrap<InheritVirtual<Node>, NodeB>
{ 
   //...
};


class NodeC : public NodeWrap<InheritVirtual<Node>, NodeB>
{ 
   //...
};

class NodeD : public NodeWrap<InheritBases<NodeB,NodeC>, NodeD>
{ 
   //...
};
模板
类继承虚拟
:公共虚拟基地
{};
模板
类继承基
:公共基地。。。
{
虚拟节点*clone()常量=0;
虚拟void()常量=0;
};
类NodeB:公共NodeWrap
{ 
//...
};
类NodeC:公共NodeWrap
{ 
//...
};
类NodeD:public NodeWrap
{ 
//...
};
跑步

inheritables
中的纯虚方法是必需的,因为所谓的支配规则()


要解决的问题是,在多个基的情况下,如何将参数转移到正确的构造函数。与
节点不同(它是一个虚拟基)允许
NodeB
NodeC
具有成员变量和非平凡构造函数是可以的。

有关协变返回的更多详细信息:随时调用
clone()
,或者您已经知道要调用它的实例的最派生的具体类型,在这种情况下,您不需要虚拟方法;或者您不知道,在这种情况下,您的代码无法使用任何比
Base*更具体的返回类型。谢谢您的回答
class NodeD : public NodeWrap<NodeB, NodeD>,
              public NodeWrap<NodeC, NodeD>
{
public:

    typedef NodeWrap<NodeB, NodeD>  BaseClassB;
    typedef NodeWrap<NodeC, NodeD>  BaseClassC;

    NodeD() { }
    NodeD(Fill * f) : BaseClassB(f), BaseClassC(f) { }

    using BaseClassB::clone;  // (1)
    virtual NodeD *clone() const { return new NodeD(*this); }       // (2)

    virtual void id() { std::cout << "NodeD\n"; }
};
 template <class Derived, class Base1, class Base2>
 class node2 : //  etc
 // or use a variadic template if you have more than two bases
template <typename Base>
class  InheritVirtual
    : public virtual Base
{};

template <typename... Bases>
class InheritBases
    : public Bases...
{
    virtual Node* clone() const = 0;
    virtual void id() const = 0;
};

class NodeB : public NodeWrap<InheritVirtual<Node>, NodeB>
{ 
   //...
};


class NodeC : public NodeWrap<InheritVirtual<Node>, NodeB>
{ 
   //...
};

class NodeD : public NodeWrap<InheritBases<NodeB,NodeC>, NodeD>
{ 
   //...
};