Reputation: 177
Basically, my question is related to name lookup and using
declaration (http://en.cppreference.com/w/cpp/language/namespace).
Suppose we have the following (definitely stupid) codes:
class Base {
public:
void fun()
{std::cout << "Base fun" << std::endl;}
};
class Derived : public Base {
public:
// Here both names "fun" are visible or not?
using Base::fun;//let's call this func_1
void fun() //let's call this func_2
{
std::cout << "Derived fun" << std::endl;
}
};
Derived d;
d.fun(); // This resolves to func_2, why?
Therefore, my understand is now we should have both names visible, and then for name lookup, there should be some ambiguity. But actually it is not. What is the reason or in other words, do I misunderstand some concepts?
Upvotes: 0
Views: 246
Reputation: 6777
The link you're referencing is for namespace
's, you should instead refer to the class
using-declaration where it states:
If the derived class already has a member with the same name, parameter list, and qualifications, the derived class member hides or overrides (doesn't conflict with) the member that is introduced from the base class.
In the case of your posted code, void fun()
in Base
is hidden by void fun()
in Derived
, so no, they're not both "visible", unless you are explicit when you call fun
, example:
class Base {
public:
void fun() { std::cout << "base" << std::endl; }
};
class Derived : public Base {
public:
using Base::fun;
void fun() { std::cout << "derived" << std::endl; }
};
Derived d;
d.fun(); // name lookup calls Derived::fun
d.Base::fun(); // explicitly call Base::fun
Additionally, since you've publicly derived from Base
, strictly speaking, you don't need the using
declaration; you would in the instance that void fun()
were protected
in Base
or you private
/protected
'ly inherited from Base
, example:
#include <iostream>
class Base {
public:
void fun() { std::cout << "base" << std::endl; }
protected:
void fun2() { std::cout << "base2" << std::endl; }
};
// class default is private
class Private : Base {
public:
// fun() won't be accessible since private inheritance and no using
// fun2 can now be accessed directly
using Base::fun2;
};
class Public : public Base {
public:
// fun is already public
using Base::fun2; // bring into scope
};
class Derived : public Base {
public:
using Base::fun;
using Base::fun2;
// overriden method fun, no conflict, choose this method if type is Derived
void fun() { std::cout << "derived" << std::endl; }
};
int main(int argc, char* argv[])
{
Private p;
Public u;
Derived d;
// generates a compiler error since Base is privately inherited
//p.fun();
p.fun2(); // OK, output: base2
u.fun(); // OK, output: base
u.fun2(); // OK, output: base2
// use Derived::fun since override
d.fun(); // OK, output: derived
d.Base::fun(); // OK, output: base
d.fun2(); // OK, output: base2
return 0;
}
Hope that can help
Upvotes: 0
Reputation: 119239
The standard has a special rule for this case.
When a using-declaration brings names from a base class into a derived class scope, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting).
([namespace.udecl]/15)
Note that as usual, you can force Base::fun
to be called by doing d.Base::fun()
.
Upvotes: 3