C++ 结合虚拟继承使用CRTP
我有一个节点层次结构,其中可以出现“菱形” 每个节点都必须是可克隆的,但我不想将克隆方法写入每个节点。所以我使用CRTPC++ 结合虚拟继承使用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"; } }; //===========
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>
{
//...
};