Consider the following program
class Node {
public:
virtual void Visit() = 0;
};
class Graph {
public:
virtual void Visit();
};
class GraphNode1 : public Node, Graph {
};
class GraphNode2 : public Node, Graph {
using Graph::Visit;
};
class GraphNode3 : public Node, Graph {
public:
virtual void Visit() {
Graph::Visit();
}
};
int main()
{
GraphNode1 a;
GraphNode2 b;
GraphNode3 c;
}
It does not compile, but complains that GraphNode1
and GraphNode2
are abstract, since Node::Visit
is pure virtual.
I would have assumed that both GraphNode1
and GraphNode2
were fine, since:
Visit
.Visit
, so there should be no ambiguity.Can anyone explain why I have to create an explicit implementation to make it work.
Node
and Graph
are unrelated classes. Which makes Node::Visit
and Graph::Visit
distinct unrelated member functions.
Neither can override the other. You seem to think Graph::Visit
is somehow "better" than Node::Visit
on account of not being pure virtual, and should therefore override it. But there is no objective reason for it. For starters, pure virtual functions can have a definition:
struct A {
virtual void thing() = 0;
};
inline void A::thing() {}
And secondly, a function can be made pure virtual when overriden:
struct A {
virtual void thing() {}
};
struct B : A {
void thing() override = 0;
};
So really, there is no reason for Node::Visit
and Graph::Visit
to interact as overriders of each other. That's why you need to be explicit and define a function yourslef that will serve as an overrider*.
* One shortcoming of C++ is that you in fact override both Node::Visit
and Graph::Visit
in GraphNode3
. IMO it's a quirk of the language (really, it should be possible to keep them unrelated). MSVC has an extension that lets you choose what to override in a more fine-grained manner.