Contents

C++ quick tips: Overloaded virtual functions

Contents

Let’s suppose that you’re working with a virtual interface defined as follows:

1
2
3
4
5
struct I {
    virtual ~I() = default;

    virtual void process(int) = 0;
};

Now, let’s have a class A that implements this interface:

1
2
3
struct A : I {
    void process(int) override {}
};

So far so good. Now, let’s say you want to add an overloaded version of process in class B. This would look like so:

1
2
3
struct B : A {
    void process(std::string) {}
};

An attempt to use this class’s original interface like so:

1
B{}.process(123);

Will result in an unexpected compilation error:

1
2
3
4
5
6
7
<source>:18:17: error: cannot convert ‘int’ to ‘std::string’ {aka ‘std::__cxx11::basic_string<char>’}
   18 |     B{}.process(123);
      |                 ^~~
      |                 |
      |                 int
<source>:14:18: note:   initializing argument 1 of ‘void B::process(std::string)’
   14 |     void process(std::string) {}

If you add -Wall to your compiler flags, you’ll see a warning:

1
2
<source>:10:10: warning: ‘virtual void A::process(int)’ was hidden [-Woverloaded-virtual=]
   10 |     void process(int) override {}

This explains the problem. B::process(std::string) is an overload which is not a part of virtual interface. Its presence hides the original interface declared in I and implemented in A.

To fix this, you need to bring the original interface into B’s scope:

1
2
3
4
5
struct B : A {
    using A::process;

    void process(std::string) {}
};

Now, B{}.process(123); Will compile and work as expected. I’m surprised that the suggestion is not a part of the warning message.