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