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";
}
};
Related
I have a base class with an implemented function and a pure virtual function which share a name, but not arguments. I can't call the function implemented in the base class from an instance of the derived class.
I've tried adding the function to the derived class instead of the base class and it works, but that would mean I have to add the function to every derived class instead of implementing it once in the base class.
I've also tried changing the functions name and it works. It seems to be due to a collision between the two overloaded functions.
template <typename T>
class Base {
public:
virtual T some_function(int x) = 0;
T some_function() {
// some code
}
}
class Derived final: public Base<int> {
int some_function() {
// some code
}
}
int main() {
Derived var = Derived();
var.some_function(3);// Compilation error
}
The above code does not compile indicating that it doesn't find the function: some_function(int).
The name some_function in Derived hides the name some_function inherited from Base. You have to bring it back into scope with a using declaration:
class Derived final: public Base<int> {
public:
using Base<int>::some_function;
int some_function() {
// some code
}
}
class Base {
public:
virtual void f();
void f(int);
virtual ~Base();
};
class Derived : public Base {
public:
void f();
};
int main()
{
Derived *ptr = new Derived;
ptr->f(1);
delete ptr;
return 0;
}
ptr->f(1); is showing the following error: "too many arguments in function call".
Why is this isn't possible? isn't derived inherited all the functions form base and is free to use any of them?
I could call it explicitly and it would work but why isn't this allowed?
What you are seeing is called hiding.
When you override the function void f() in the Derived class, you hide all other variants of the f function in the Base class.
You can solve this with the using keyword:
class Derived : public Base {
public:
using Base::f; // Pull all `f` symbols from the base class into the scope of this class
void f() override; // Override the non-argument version
};
As mentioned by #Some Programming Dude : it is because of Hiding.
To understand hiding in relatively simpler language
Inheritance is meant to bring Baseclass variables / functions in Derived class.
But, on 1 condition : "If its not already available in Derived Class"
Since f() is already available in Derived, it doesn't make sense to look at Base class from compiler perspective.
That's the precise reason why you need to scope clarify while calling this function
void main()
{
Derived *ptr = new Derived;
ptr->Base::f(1);
delete ptr;
}
Suppose for time being that Derived do have the access to the function void Base::f(int);. Then it will be a case of function overloading. But, this is invalid case of function overloading since one function f(int);is in Base and other function f(); is in Derived. Function Overloading happens inside a single class. Function Overriding happens across classes. The example you posted is a case of Name Hiding in Inheritance
"Derived *ptr" This definition will only allow "ptr" to access all the member functions which are defined via Derived class or its child class. But, it will not allow u to access the member functions which are coming in Derived class because of inheritance.
If u want to access base class version of function "f" then use "Base *ptr" and it will choose the correct version of function automatically as shown :)
class Base {
public:
virtual void f()
{
cout<<"Here 2"<<endl;
}
void f(int x)
{
cout<<"Here 1"<<endl;
}
virtual ~Base() {}
};
class Derived : public Base {
public:
void f()
{
cout<<"Here 3"<<endl;
}
virtual ~Derived() {}
};
int main()
{
Base *ptr = new Derived;
ptr->f(1);
delete ptr;
return 0;
}
output is
Here 1
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";
}
};
Please provide me with a specific answer why function overriding hides the functions that are overloaded in base class.
class Base{
public:
fun(int,int);
fun(B);
};
class Derived:public Base
{
public:
fun();
};
int main()
{
Derived d;
d.fun(1,2); // error
return 0;
}
TTBOMK this doesn't have a real technical reason, it's just that Stroustrup, when creating the language, considered this to be the better default. (In this it's similar to the rule that rvalues do not implicitly bind to non-const references.)
You can easily work around it be explicitly bringing base class versions into the derived class' scope:
class Base {
public:
void fun(int,int);
void fun(Base);
};
class Derived : public Base {
public:
using Base::fun;
void fun();
};
Also refer WHY link as it tells why base overloaded method is hidden in derived class: WHY
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.