У меня есть абстрактный класс 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;
};
Чтобы я мог вызывать совпадения в шаблонной функции следующим образом:
template <class T>
void pathComp(Node<T>& currNode, Node<T>& rootNode) {
Node<T> *node = &currNode;
while (node->matches(rootNode)) {
...
}
}
Я не мог заставить этот метод работать, к тому же мне не нравилось, что мне, казалось бы, нужно было иметь class NodeImpl : public Node<NodeImpl>
в качестве наследства, что-то в этом казалось не совсем правильным. Любой совет относительно того, был ли я на правильных линиях или нет, был бы замечательным!
Node
по контракту обязал подклассы реализовать методmatches
, но только междуNode
подклассами одного и того же типа, как бы я это сделал? Я пробовал использовать шаблоны и иметьbool matches(const T& node)
, но при этом немного запутался. 15.03.2014matches()
должен принимать общийNode
в качестве входных данных, а затем каждый класс должен будет использоватьdynamic_cast
, чтобы проверить, является ли ввод правильным типом, прежде чем что-то с ним делать, например:bool A::matches(const Node &node) const { const A *a = dynamic_cast<const A*>(&node); if (a) { ... } else return false; }
15.03.2014