Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using-declaration in derived class does not hide same function derived from base class

Tags:

Have a look at the following code:

struct A { public:     virtual void f(){std::cout << "in A";}; };  struct B : A{ public:    virtual void f(){std::cout << "in B";};    int a; };  struct C : B{     using A::f;     void test(){f();} };   int main()  {     C c;     c.f(); // calls B::f, the final overrider     c.C::f(); // calls A::f because of the using-declaration     c.test(); //calls B::f     return 0; } 

Per my understanding, the B::f() in C should hide the A::f() which is brought to C by using-declaration; if so, then why does c.C::f() still call A::f()?

If c.C::f() calls A::f(), that should mean that in the scope of C, f() should be always refer to A::f(), this is the function of the using-declaration. Then why in the C::test(), call to f() is still evaluated to B::f()?

like image 277
Liu Nick Avatar asked Feb 11 '15 08:02

Liu Nick


People also ask

Can base and derived class have same function?

Suppose, the same function is defined in both the derived class and the based class. Now if we call this function using the object of the derived class, the function of the derived class is executed. This is known as function overriding in C++. The function in derived class overrides the function in base class.

What does derived class does not inherit from the base class?

Following are the properties which a derived class doesn't inherit from its parent class : 1) The base class's constructors and destructor. 2) The base class's friend functions. 3) Overloaded operators of the base class.

What is the use of using declaration in C++?

A using declaration in a definition of a class A allows you to introduce a name of a data member or member function from a base class of A into the scope of A .

What is the use of using declaration?

A using declaration introduces an unqualified name as a synonym for an entity declared elsewhere. It allows a single name from a specific namespace to be used without explicit qualification in the declaration region in which it appears.


1 Answers

Very nice question, a complicated case of name lookup.

Basically, when the name f is looked up in the scope of C, it always finds A::f due to the using-declaration. So all the calls c.f(), c.C::f(), and f() in C::test(), resolve the name f to A::f.

Next comes virtual dispatch. If a virtual function is called by an unqualified name, dynamic dispatch happens and the final overrider is called. This covers c.f() and the f() call in C::test(), since these are unqualified.

The call c.C::f() uses a qualified name for f, which suppresses dynamic dispatch and the function to which the name resolved is called directly. Since that function is A::f (thanks to the using-declaration), A::f is called non-virtually. The relevant rules follow (quoting C++14 final draft N4140, emphasis mine):

§10.3/15

Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism.

§5.2.2/1

... If the selected function is non-virtual, or if the id-expression in the class member access expression is a qualified-id, that function is called. Otherwise, its final overrider (10.3) in the dynamic type of the object expression is called; such a call is referred to as a virtual function call.

like image 135
Angew is no longer proud of SO Avatar answered Sep 29 '22 12:09

Angew is no longer proud of SO