I don't understand what is wrong with this code. It looks like an incredible trap !
This code :
class Foo
{
public:
virtual double foo(double x) const = 0;
double foo(int x) const { return (double)(x + x); }
};
class Bar : public Foo
{
public:
virtual double foo(double x) const { return x * x; }
};
int main()
{
Bar* b = new Bar;
Foo* f = b;
std::cout << b->foo(3) << " " << f->foo(3) << std::endl;
std::cout << b->foo(5.0) << " " << f->foo(5.0) << std::endl;
return 0;
}
prints the following output :
9 6
25 25
I deduce that Bar::foo(double) const
is called with an implicit cast when the type of the pointer is Bar*
. But why such a thing is possible without any warning ?
I work with GCC 4.7.2. I compiled with g++ -Wall foobar.cpp -o foobar.exe
This is due to name hiding.
When you declare a function called
foo
inBar
, you hide all declarations with the same name inFoo
.As such, when the static type of the pointer is
Bar
, the compiler only finds the version inBar
which takes adouble
, so it implicitly converts theint
to satisfy this.If you want the
int
version inFoo
to be visible, add ausing
declaration:When the type is
Bar*
, only one version of the method is visible, the one with thedouble
parameter.Base methods with the same name (but different signature) are hidden.
To make them available, you can use
using Foo::foo
in the derived class.Depending on your compiler, I think you might also get warnings regarding the implicit conversion, or the fact that you apparently want to call a hidden method.
In
Foo
there are two overloads offoo
, one that takes adouble
and another that takes anint
.In
Bar
there is one overload offoo
, the one that takes adouble
. This overload hides all functions with the same name from the base classes. This is called name hiding.A fix would be to employ using declaration to bring the other
foo
overloads from the base class in scope ofFoo
derived class: