Reputation: 15501
I was reading the C++0x FAQ by Stroustrup and got stuck with this code. Consider the following code
struct A
{
void f(double)
{
std::cout << "in double" << std::endl;
}
};
struct B : A
{
void f(int)
{
std::cout << "in int" << std::endl;
}
};
int main()
{
A a; a.f(10.10); // as expected, A.f will get called
B b; b.f(10.10); // This calls b.f and we lose the .10 here
return 0;
}
My understanding was when a type is inherited, all protected and public members will be accessible from the derived class. But according to this example, it looks like I am wrong. I was expecting the b.f will call base classes f. I got the expected result by changing the derived class like
struct B : A
{
using A::f;
void f(int)
{
std::cout << "in int" << std::endl;
}
};
Questions
Upvotes: 7
Views: 716
Reputation: 2551
The first version of code should really call B::f. You re-define the symbol "f" in struct "B", so it hides the original symbol "f" from struct "A". It is not an overload, as it may seem.
Whenever compiler meets b.f(), it searches the "B" struct for a symbol "f". It is present there, so the compiler decides to call B::f(int), converting double to int. It sees no need to scan the parent class for a more suitable function...
Yet, when you add "using A::f", it is an explict directive for the compiler to scan a parent class for symbol "f". Now, B class has two overloaded functions: for int and for double.
I also believe, that you could write b.A::f() without using "using" directive in the original example...
Upvotes: 1
Reputation: 9817
The first code works as c++ is designed to work.
Overloading resolution follows a very complicated set of rules. From Stroustrup's c++ bible 15.2.2 "[A]mbiguities between functions from different base classes are not resolved based on argument types."
He goes on to explain the use of "using" as you have described.
This was a design decision in the language.
I tend to follow the Stroustrup book rather than the standard, but I'm sure it is in there.
[Edit]
Here it is (from the standard):
Chapter 13
When two or more different declarations are specified for a single name in the same scope, that name is said to be overloaded.
And then:
13.2 Declaration matching
1 Two function declarations of the same name refer to the same function if they are in the same scope and have equivalent parameter declarations (13.1). A function member of a derived class is not in the same scope as a function member of the same name in a base class.
Upvotes: 4
Reputation: 35450
Its because A::f is "hidden" rather than "overloaded" or "overridden". Refer:
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9
Upvotes: 5
Reputation: 7180
In the first case, the base class method 'f' is hidden by the derived class method. In C++ there is no overloading across scopes; that is why it is not called. The C++ standard explains all the member name lookup rules in the section 10.2 Member name lookup [class.member.lookup]. HTH
Upvotes: 1
Reputation: 29322
In C++, there is no overloading across scopes, scoped in derived classes are not an exception. (According to The C++ Programming Language)
For more info, check out http://www.research.att.com/~bs/bs_faq2.html#overloadderived
Upvotes: 1
Reputation: 17258
Search for overload resolution. A similar, but not identical question.
Upvotes: 2