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

时间:2014-03-15 04:34:28

标签: c++ pointers inheritance abstract-class pure-virtual

我有一个抽象类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

E.g。我希望以下内容从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;
};

这样我就可以在模板函数中调用匹配项,如下所示:

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

我无法完全使用这种方法,而且我不喜欢我似乎必须拥有class NodeImpl : public Node<NodeImpl>作为我的继承,这似乎不太合适。关于我是否在合适的线路上的任何建议都会很棒!

2 个答案:

答案 0 :(得分:1)

一般来说,你不能真正做到这一点,因为它不是类型安全的。例如:

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

答案 1 :(得分:0)

你应该尊重超类的合同签名。然后,如果你需要 要访问子类属性,只需根据需要强制转换为子类。