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.
Related
recently i came to know this - if a derived class redefines base class member method(s) then all the base class methods with same name become hidden in derived class.
#include<iostream>
using namespace std;
class Base
{
public:
int fun()
{
cout<<"Base::fun() called";
}
int fun(int i)
{
cout<<"Base::fun(int i) called";
}
};
class Derived: public Base
{
public:
int fun()
{
cout<<"Derived::fun() called";
}
};
int main()
{
Derived d;
d.fun(5); // Compiler Error
return 0;
}
Error :
In function 'int main()':
Line 30: error: no matching function for call to 'Derived::fun(int)'
compilation terminated due to -Wfatal-errors.
but just wanna know the reason behind it? why is it not calling fun(int i) method of Base Class since Derived class is derived from Base
The fundamental reason is to make code more robust.
struct Base {
};
struct Derived : Base {
void f(long);
void g() { f(3); } // calls Derived::f
}
Now suppose Base is defined in a library, and you get an update to that library and the update changes the definition of Base:
struct Base {
void f(int);
};
Now suppose that searches for overloaded functions didn't stop when a name was found. In that case, Derived::g would call Base::f instead of Derived::f, and your derived class would quietly do something completely different from what it did before, and different from what it was designed and documented to do.
You've already discovered that derived-class overloads will shadow (prevent the visibility of) base-class methods by the same name but different parameters. Let's just claim this was done for some historical or perceived safety reason, and look at a fix:
class Derived: public Base
{
public:
using Base::fun; // expose the base-class method
int fun()
{
cout<<"Derived::fun() called";
}
};
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.
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.
Take the example below. What term do you use to describe an inheriting class with different parameters then the base class? I understand that subbase is implicitly calling base(). You wouldn't call this overriding, correct, since the base constructor is still called?
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
class base
{
public:
base()
{
cout << "Hello!\n";
}
};
class subbase : public base
{
public:
subbase(string s)
{
cout << s << endl;
}
};
int main()
{
subbase test("Hello World!\n");
return 0;
}
Overloaded my friend. It has same method name but differing parameter or return type
But in this case you are just creating whole new constructor. Not really inheriting or anything.
Overloading: When you change the signature of the inherited functions in the derived class.
Redefinition(In case of normal functions)/Overriding(In case of virtual functions): When you keep the signature of the base class functions same in the derived class. But you change the implementation part.
But I am not talking in terms of Constructors here. I am talking about the usual member functions of the class.
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.