如何以抽象类作为参数继承和实现纯虚方法

How to inherit and implement a pure virtual method with the abstract class as a parameter?

本文关键字:实现 方法 继承 参数 抽象类      更新时间:2023-10-16

我有一个抽象类Node,它包含一个纯虚拟方法存根matches,需要Node的另一个实例(即Node子类的实例)作为参数。

class Node; // forward declaration
class Node {
public:
    Node() : parentNode(this) {}
    virtual ~Node() {}
    Node* parentNode;
    virtual bool matches(const Node& node) const = 0;
};

我如何在子类中实现matches,使参数可以是子类类型而不是Node ?

。我想要以下内容注册为Node的合同实现版本,这样我就可以访问NodeImpl特定属性作为函数的一部分,否则我将无法这样做:

class NodeImpl : public Node {
private:
    int foo;
    ...
};
...
bool NodeImpl::matches(const NodeImpl& n) const {
    return this->foo == n.foo;
}

(我确实尝试过使用模板来实现这种效果,但我不确定我做得是否正确。我发现我自己在我的代码中传播模板,并遇到了无数的错误,并且希望在我浪费更多的时间在可能也是错误的做事方式之前得到一个正确的方法是什么。

我尝试的是:

template <class T>
class Node;
template <class T>
class Node {
public:
    Node() : parentNode(this) {}
    virtual ~Node() {}
    Node* parentNode;
    virtual bool matches(const T& node) const = 0;
};

这样我就可以在模板函数中调用match了,像这样:

template <class T>
void pathComp(Node<T>& currNode, Node<T>& rootNode) {
    Node<T> *node = &currNode;
    while (node->matches(rootNode)) {
        ...
    }
}

我不能很好地让这个方法工作,加上我不喜欢我似乎必须把class NodeImpl : public Node<NodeImpl>作为我的继承,这似乎不太对。任何关于我是否在正确的路线上的建议将是伟大的!

通常不能这样做,因为它不是类型安全的。例如:

struct Node { virtual bool matches(const Node &) const = 0; }
struct NodeA : Node { virtual bool matches(const NodeA &) const; };
struct NodeB : Node { virtual bool matches(const NodeB &) const; };
NodeA a; // compiler doesn't allow, but if it did...
NodeB b;
Node &c = a;
c.matches(b); // oops!

你谈论实现它的方式,会有一个假设,ba是相同的类型,但是编译器没有办法验证这个假设,所以它不允许它。

但是,如果您使用的是两个相同类型的节点,则始终可以使matches()函数不是虚拟的:

struct Node {   }
struct NodeA : Node {  bool matches(const NodeA &) const; };
NodeA a1;
NodeA a2;
a1.matches(a2); // fine

您应该遵守超类的合同签名。如果你需要要访问子类属性,只需根据需要转换为子类。