我有一个抽象类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>
作为我的继承,这似乎不太合适。关于我是否在合适的线路上的任何建议都会很棒!
答案 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!
您正在讨论实现它的方式,假设b
与a
的类型相同,但编译器无法一般性地验证该假设,因此它不会允许它。
但是,如果您使用的是同一类型的两个节点,则始终可以使matches()
函数不是虚拟的:
struct Node { }
struct NodeA : Node { bool matches(const NodeA &) const; };
NodeA a1;
NodeA a2;
a1.matches(a2); // fine
答案 1 :(得分:0)
你应该尊重超类的合同签名。然后,如果你需要 要访问子类属性,只需根据需要强制转换为子类。