Magnar Myrtveit
Magnar Myrtveit

Reputation: 2740

Implement pure virtual function with using

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:

Can anyone explain why I have to create an explicit implementation to make it work.

Upvotes: 1

Views: 374

Answers (1)

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.

Upvotes: 4

Related Questions