Wednesday, September 16, 2009

A(nother) counter intuitive C++ (mis)feature

I've been using C++ for about 12 years now.  Which means I don't know if very well.  Early on in my C++ career I thought I had a good grasp of the language, but C++ is one of those languages that the more you learn the more you understand how hopeless it is to fully understand it.  Every month or so I'm confronted with some new corner case that I didn't know about.  Last months mis-feature had to due with overloading and overriding.  
Consider the following code:
class Bar
{
    public:
        virtual void method(int a)
        {
            std::cout << "Bar " << a << std::endl;
        }
};

class Baz : public Bar
{
    public:
        virtual void foo(std::string a)
        {
            std::cout << "Baz " << a << std::endl;
        }
};
int main()
{
    int i = 9;
    std::string s = "9";

    Baz *b1 = new Baz();

    b1->method(i);
    b1->method(s);
}

If you compile this code (with g++) you'll get the following errors:
error: invalid conversion from ‘int’ to ‘const char*’
error:   initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits, _Alloc = std::allocator]’


This caught me by surprise.  I had assumed that the compiler would match the method signatures after the method names were mangled, and thus method(std::string) would not hide method(int).  It turns out that methods are matched only by the name, and after the match has been found (in this case finding the method(std::string) the type checker validates the parameter types.  While I can understand this could make the compiler more efficient, it seem that by default the C++ compiler does the wrong (non-intuitive) thing.

So how do you make the compiler do what you want? You just need to add a "using" line right before Baz's method as follows:
...
using Bar::method;
virtual void method(std::string a)
{
...
}
...

Of course you could have guessed that. Right?

1 comment:

  1. It's also nice that you see all the template guts in the error messages.

    ReplyDelete