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?
It's also nice that you see all the template guts in the error messages.
ReplyDelete