Declaration matching

I encountered an interesting problem today. Consider the following piece of code:

namespace Test
struct Lol {};
struct Cat {};

struct Foo
    virtual void Do(Lol&);
    virtual void Do(Cat&);
struct Bar : public Foo
    virtual void Do(Lol&);
    void DoSomethingElse()
        Cat cat;

Question: what happens when you execute Bar::DoSomethingElse?

Answer: nothing, as trying to compile this piece of code will result in the following error: ‘Test::Bar::Do’ : cannot convert parameter 1 from ‘Test::Cat’ to ‘Test::Lol &’. At first, I was really surprised, I expected it to call Foo::Do. As it turns out, that’s a tricky case of mixing virtuals & method hiding. According to C++ standard, two function declarations of the same name refer to the same function if they are in the same scope and take same parameters. Function member of a derived class is not in the same scope as a function member in a base class. So, what happens here, when we declara Do in Bar class, we also hide all previous declarations of function with this name. From now on, only Bar::Do(Lol&) is visible. It kinda makes sense when you think about it, but at first it was really counterintuitive for me. Solution? Add this to Bar:

    using Foo::Do;

Even safer way - rename one of functions. It’s moments like this that make me realize how many dark corners C++ has.

Old comments

Thomas 2010-11-21 22:55:17

at least you will get a warning i guess…

islet8 2010-11-13 07:10:05

I won’t use function override and overload at the same time, it’ll make trouble for other coders and readers.C++ has too many tricks to make us working inefficiently.

lzprgmr 2010-11-12 05:04:51

In fact, it has nothing to do with virtual — remove the virtual keyword you will get the same result.

admin 2010-11-12 05:20:25

That’s true, but if you’re using same method name/arguments and no virtual keyword, you most probably want to hide base methods.

Michal 2010-11-11 12:11:45

See also: Effective C++ Item 33
Bardzo ciekawy blog. Pozdrowienia :)

More Reading