I believe that the best answer is already given here : Why does an overridden function in the derived class hide other overloads of the base class?
But I am confused a little bit, specially with the statement :
In order to override this behavior, an explicit action is required from the user: originally a redeclaration of inherited method(s) (currently deprecated), now an explicit use of using-declaration.
Suppose I have the following program :
#include <iostream>
using namespace std;
class Base
{
public:
int f(int i)
{
cout << "f(int): ";
return i+3;
}
};
class Derived : public Base
{
public:
double f(double d)
{
cout << "f(double): ";
return d+3.3;
}
};
int main()
{
Derived* dp = new Derived;
cout << dp->f(3) << '\n';
cout << dp->f(3.3) << '\n';
delete dp;
return 0;
}
I have two questions :
Can I assume, w.r.t derived class object, the int f(int i) function does not exist at all. This is not inherited because of name hiding.
If I have to use this function in Derived class, I have to define it again in derived class?
Can I assume, w.r.t derived class object, the int f(int i) function does not exist at all. This is not inherited because of name hiding.
It is inherited, it's just ... hidden, can't be found if you don't specify the scope (unqualified name lookup. You can specify it explicitly with scope resolution operator :: (qualified name lookup) :
dp->Base::f(3);
If I have to use this function in Derived class, I have to define it again in derived class?
As the quoted answer said, you can do it with "an explicit use of using-declaration".
class Derived : public Base
{
public:
using Base::f;
...
};
EDIT (for supplemental questions from comment)
If it's name hidden, that means I can declare it again ? Same name, same parameters?
Yes, you can. It's still name hiding.
If yes, what if I also added using Base::f along with the new declaration? Will it result in double definition?
No, it's not double definition. Using declaration just introduces the name into the derived class scope. And the member function declared in derived class will hide the one introduced from base class, it's still name hiding. (Note you still could call the one of base class by dp->Base::f(3);.)
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.
Related
I was trying out few concepts of function hiding in c++.
So here in the derived class I've used scope resolution operator using base::fun to provide scope of base class in derived class. My objective is to print cout<<" base "<< x; but the output only prints derived class cout. Any reasons why and how to solve? i.e it should print both base and derived class value. I'm new to c++, so sorry for any mistakes.The code is shown below:
#include <stdio.h>
#include <iostream>
using namespace std;
class base
{
public:
int fun(int x)
{
cout<<" base "<< x;
return x;
}
};
class derived:public base
{
public:
using base::fun;
void fun(int a)
{
cout<<" derived "<< a;
}
};
int main()
{
derived d;
d.fun(10);
return 0;
}
it should print both base and derived class value
No. Only one function would be selected and called. Then the problem is that which one should be selected. In this case derived::fun is selected; because for using declaration,
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.
You might call the base one by specifying explicitly:
d.base::fun(10);
LIVE
it should print both base and derived class value
Why do you think it should? There is a single function call,
so theoretically, it should be either derived::fun or base::fun, not both. Since d is of type derived then derived::fun gets called.
Say there are two classes: Base and Derived. The code is listed below. My question is, how does the program know d.print() (tagged with A in code) is meant to call Derived::print() instead of Base::print()?
Please note that I deliberately added using Base::print; to confuse the compiler. These two print() methods have the same signature (am I right?) and are not hiding each other because of the using statement.
#include <iostream>
using namespace std;
class Base {
public:
void print() { cout << "print() of Base is called\n"; }
};
class Derived : public Base {
public:
void print() { cout << "print() of Derived is called\n"; }
using Base::print; // I delibarately added this line
};
int main() {
Derived d;
d.print(); // A
Base *pBase = (Base *)&d;
pBase->print(); // B
}
The result is
print() of Derived is called
print() of Base is called
Edit: the accepted answer gave a quote. For readers' convenience I paste the (nearly) whole quoted paragraph here, split in sentence:
Using-declaration introduces a member of a base class into the derived class definition, such as to expose a protected member of base as public member of derived.. (that's what I expected)
If the name is the name of an overloaded member function of the base class, all base class member functions with that name are introduced. (that's what I expected, too)
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. (solved my problem)
The explicitly introduced using does not hide the method you have in the derived class because of this rule (from the cppreference documentation for using)
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.
The compiler is not confused, it's doing the right thing. The using is not hiding the print() method in the derived class because it defines a print() method.
When you call print() with a Base pointer, print() is not virtual the base pointer can only call the method that is registered with the static type of the thing it is pointing to, i.e. Base::print()
Generally, we wish to use private inheritance to hide the implementation details to the base class. If this is true,
1) Why is the name publicizing feature is there again ? Is it only for language completeness or is there any practical usage also?
2) Even though I publicize the base class function name, a derived class can still declare another function with same name. Please consider the following code.
#include "iostream"
using namespace std;
class Base {
public:
int zoo;
Base() {zoo =5;}
int sleep() const {return 3;}
};
class Derived : Base { // Private inheritance
public:
using Base::zoo;
using Base::sleep;
int sleep() const { return 4.0; }
};
int main() {
Derived der;
der.sleep();
cout<<" zoo is : "<<der.zoo<<endl;
cout<<" Sleep is : "<<der.sleep()<<endl;
}
In the above snippet, even though we publicize the name, we can still declare the name in derived class, and we can access the base class version of member variables. How the memory is managed?
Thank you.
http://en.cppreference.com/w/cpp/language/using_declaration
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.
That link has specific examples of exactly what you are doing an re-iterates what I quoted above and how the base member is simply hidden by the derived member.
I made a class with virtual function f() then in the derived class I rewrote it like the following f(int) why can't I access the base class function throw the child instance ?
class B{
public:
B(){cout<<"B const, ";}
virtual void vf2(){cout<<"b.Vf2, ";}
};
class C:public B{
public:
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
int main()
{
C c;
c.vf2();//error should be vf2(2)
}
You have to do using B::vf2 so that the function is considered during name lookup. Otherwise as soon as the compiler finds a function name that matches while traversing the inheritance tree from child -> parent -> grand parent etc etc., the traversal stops.
class C:public B{
public:
using B::vf2;
C(){cout<<"C const, ";}
void vf2(int){cout<<"c.Vf2, ";}
};
You are encountering name hiding. Here is an explanation of why it happens ?
In C++, a derived class hides any base class member of the same name. You can still access the base class member by explicitly qualifying it though:
int main()
{
C c;
c.B::vf2();
}
You were caught by name hiding.
Name hiding creeps up everywhere in C++:
int a = 0
int main(int argc, char* argv[]) {
std::string a;
for (int i = 0; i != argc; ++i) {
a += argc[i]; // okay, refers to std::string a; not int a;
a += " ";
}
}
And it also appears with Base and Derived classes.
The idea behind name hiding is robustness in the face of changes. If this didn't exist, in this particular case, then consider what would happen to:
class Base {
};
class Derived: public Base {
public:
void foo(int i) {
std::cout << i << "\n";
}
};
int main() {
Derived d;
d.foo(1.0);
}
If I were to add a foo overload to Base that were a better match (ie, taking a double directly):
void Base::foo(double i) {
sleep(i);
}
Now, instead of printing 1, this program would sleep for 1 second!
This would be crazy right ? It would mean that anytime you wish to extend a base class, you need to look at all the derived classes and make sure you don't accidentally steal some method calls from them!!
To be able to extend a base class without ruining the derived classes, name hiding comes into play.
The using directive allows you to import the methods you truly need in your derived class and the rest are safely ignored. This is a white-listing approach.
When you overload a member function in a base class with a version in the derived class the base class function is hidden. That is, you need to either explicitly qualify calls to the base class function or you need a using declaration to make the base class function visible via objects of the derived class:
struct base {
void foo();
void bar();
};
struct derived: base {
void foo(int);
using base::foo;
void bar(int);
};
int main() {
derived().foo(); // OK: using declaration was used
derived().bar(); // ERROR: the base class version is hidden
derived().base::bar(); // OK: ... but can be accessed if explicitly requested
}
The reason this is done is that it was considered confusing and/or dangerous when a member function is declared by a derived function but a potenially better match is selected from a base class (obviously, this only really applies to member functions with the same number of arguments). There is also a pitfall when the base class used to not have a certain member function: you don't want you program to suddenly call a different member function just because a member function is being added to the base class.
The main annoyance with hiding member functions from bases is when there is a set of public virtual functions and you only want to override one of them in a derived class. Although just adding the override doesn't change the interface using a pointer or a reference to the base class, the derived class can possibly not used in a natural way. The conventional work-around for this to have public, non-virtual overload which dispatch to protected virtual functions. The virtual member function in the various facets in the C++ standard library are an example of this technique.
In C++, will a member function of a base class be overridden by its derived class function of the same name, even if its prototype (parameters' count, type and constness) is different? I guess this a silly question, since many websites says that the function prototype should be the same for that to happen; but why doesn't the below code compile? It's a very simple case of inheritance, I believe.
#include <iostream>
using std::cout;
using std::endl;
class A {};
class B {};
class X
{
public:
void spray(A&)
{
cout << "Class A" << endl;
}
};
class Y : public X
{
public:
void spray(B&)
{
cout << "Class B" << endl;
}
};
int main()
{
A a;
B b;
Y y;
y.spray(a);
y.spray(b);
return 0;
}
GCC throws
error: no matching function for call to `Y::spray(A&)'
note: candidates are: void Y::spray(B&)
The term used to describe this is "hiding", rather than "overriding". A member of a derived class will, by default, make any members of base classes with the same name inaccessible, whether or not they have the same signature. If you want to access the base class members, you can pull them into the derived class with a using declaration. In this case, add the following to class Y:
using X::spray;
That's so called 'hiding': Y::spray hides X::spray.
Add using directive:
class Y : public X
{
public:
using X::spray;
// ...
};
Classes are scopes and a class scope is nested in its parent. You have exactly the same behavior with other nested scopes (namespaces, blocks).
What happen is that when the name lookup searches for the definition of a name, it looks in the current namespace, then in the englobing namespace and so on until it find one definition; the search then stop (that's without taking into account the complications introduced by argument dependent name lookup -- the part of the rules which allows to use a function defined in the namespace of one of its argument).