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
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";
}
};
Is there any point to making virtual member functions, overridden from a base class private, if those are public in the base class?
struct base {
virtual void a();
};
struct derived : base {
// ...
private:
void a() override;
};
If you are forced to do a 2-phase construction on the implementation class (i.e. have an init() method as well as or instead of a constructor that has to be called (I know, but there are reasons), then this stops you calling any /other/ methods directly on the instance pointer before you pass it back as an interface pointer. Go the extra mile, make the inheritance private, and have your one public init function return the interface pointer!
Another reason is you just don't /need/ to write public: in a final implementation class declaration, so then by default everything is private. But why you would do that and use struct instead of class I don't know. Perhaps this was converted from class at some point due to a style war?
Looking at your design, I see one cannot call derived::a directly, but only through a base interface.
Is there any point? Consider that, once we have a derived instance, we can always up-cast to its base, so given
derived d;
while d.a() wouldn't compile, we can always do
base & b = d;
b.a(); //which actually calls derived::a
In other words: derived::a is not that private, after all, and I would discourage this design, which can be confusing to the user.
Things change if the members private in derived are private in base, as well: this time it is clear that they just cannot be called directly, outside base or derived.
Let's say we have a couple of functions, and want them to be called conditionally, according to a value passed as an argument to a third one:
struct base
{
void dosomething(bool x)
{
if(x)
{
do_this();
}
else
{
do_that();
}
}
private:
virtual void do_this(){}
virtual void do_that(){}
};
Thus a derived class could be like:
struct derived : base
{
private:
void do_this() override { }
void do_that() override { }
};
and no other class can call them, unless it extended base itself:
derived d;
d.dosomething(true); //will call do_this() in derived
d.dosomething(false); //will call do_that() in derived
d.do_that() //won't compile
Yes, if you inherit the base class as private. Otherwise, it is more of a weird explicit-like restriction - user has to has to make an explicit conversion to use the function - it is generally ill advised as few will be able to comprehend the author's intention.
If you want to restrict some functions from base class, make a private/protected inheritance and via using keyword declare which base-methods you want to be protected/public in the derived class.
The same reasoning as for non-virtual methods applies: If only the class itself is supposed to call it make it private.
Consider the template method pattern:
struct base {
void foo() { a() ; b(); }
virtual void a() = 0;
virtual void b() = 0;
};
struct derived : base {
private:
void a() override {}
void b() override {}
};
int main()
{
derived().foo();
}
Perhaps a and b should have been protected, but anyhow the derived can change accesibility and it requires some documentation so that derived knows how it is supposed to implement a and b.
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'm slightly confused about runtime polymorphism. Correct me if I am wrong, but to my knowledge, runtime polymorphism means that function definitions will get resolved at runtime.
Take this example:
class a
{
a();
~a();
void baseclass();
}
class b: class a
{
b();
~b();
void derivedclass1();
}
class c: class a
{
c();
~c();
void derivedclass2();
}
Calling methodology:
b derived1;
a *baseptr = &derived1; //here base pointer knows that i'm pointing to derived class b.
baseptr->derivedclass1();
In the above calling methodology, the base class knows that it's pointing to derived class b.
So where does the ambiguity exist?
In what cases will the function definitions get resolved at runtime?
This code, at run time, calls the correct version of f() depending on the type of object (A or B) that was actually created - no "ambiguity". The type cannot be known at compile-time, because it is selected randomly at run-time.
struct A {
virtual ~A() {}
virtual void f() {}
};
struct B : public A {
virtual void f() {}
};
int main() {
A * a = 0;
if ( rand() % 2 ) {
a = new A;
}
else {
a = new B;
}
a->f(); // calls correct f()
delete a;
}
There is no ambiguity exists in the example provided.
If the base class has the same function name as the derived class, and if you call in the way you specified, it will call the base class's function instead of the derived class one.
In such cases, you can use the virtual keyword, to ensure that the function gets called from the object that it is currently being pointed. It is resolved during the run time.
Here you can find more explanation..
Turn this
void baseclass();
to
virtual void baseclass();
Override this in your Derived classes b and c. Then
b *derived1 = new derived1 ();
a *baseptr = derived1; //base pointer pointing to derived class b.
baseptr->baseclass();
will invoke derived1 definition, expressing run time polymorphism. And do remember about making your destructor virtual in Base. Some basic reading material for polymorphism
Runtime means that exact method will be known only at run time. Consider this example:
class BaseClass
{
public:
virtual void method() {...};
};
class DerivedClassA : public BaseClass
{
virtual void method() {...};
};
class DerivedClassB : public BaseClass
{
virtual void method() {...};
};
void func(BaseClass* a)
{
a->method();
}
When you implement your ::func() you don't know exactly type of instance pointed by BaseClass* a. It might be DerivedClassA or DerivedClassB instance etc.
You should realize, that runtime polymorphism requires special support from language (and maybe some overhead for calling "virtual" functions). In C++ you "request" for dynamic polymorphism by declaring methods of base class "virtual" and using public inheritance.
You need to have some useful business method declared in the base and in each derived class. Then you have code such as
a->someMethod();
Now the a pointer might point to an instance of any of the derived classes, and so the type of what a is pointing to must determine which someMethod() is called.
Lets have an experiment
#include <iostream>
using namespace std;
class aBaseClass
{
public:
void testFunction(){cout<<"hello base";}///Not declared as virtual!!!!
};
class aDerivedClass:public aBaseClass
{
public:
void testFunction(){cout<<"hello derived one";}
};
class anotherDerivedClass:public aDerivedClass
{
public:
void testFunction(){cout<<"hello derived two";}
};
int main()
{
aBaseClass *aBaseClassPointer;
aBaseClassPointer=new aDerivedClass;
aBaseClassPointer->testFunction();
}
The above code does not support run time polymorphism. Lets run and analyze it.
The output is
hello base
Just change the line void testFunction(){cout<<"hello base";} to virtual void testFunction(){cout<<"hello base";} in aBaseClass. Run and analyze it. We see that runtime polymorphism is achieved. The calling of appropriate function is determined at run time.
Again change the line aBaseClassPointer=new aDerivedClass to aBaseClassPointer=new anotherDerivedClass in main function and see the output. Thus the appropriate function calling is determined at run time (when the program is running).
I know why I want to use private virtual functions, but how exactly can I implement them?
For example:
class Base{
[...]
private:
virtual void func() = 0;
[...]
};
class Derived1: public Base{
void func()
{ //short implementation is ok here
}
};
class Derived2: public Base{
void func(); //long implementation elsewhere (in cpp file)
};
[...]
void Derived2::func()
{ //long implementation
}
The first version is ok but not always possible.
Isn't the second version simply name hiding? How do you define the Base::func() of Derived2, if you cannot do it within the class declaration of Dereived2?
Thanks
How do you define the Base::func() of Derived2, if you cannot do it within the class declaration of Dereived2?
You don't define "Base::func() of Derived2" (whatever this might be), you define Derived2::func(). This compiles just fine for me:
#include <iostream>
class Base{
private:
virtual void foo() = 0;
public:
void bar() {foo();}
};
class Derived: public Base{
void foo();
};
void Derived::foo()
{
std::cout << "inside of 'Derived1::foo()'\n";
}
int main()
{
Derived d;
Base& b = d;
b.bar();
return 0;
}
What's your problem with it?
Polymorphism and accessibility are two separate concepts. You can always override a base class' private virtual function, but you won't be able to call the base class version from anywhere but the base class itself. Also, C++ FAQ Lite has a pretty lengthy entry on the subject.
For what I understand here, you're trying to do polymorphism.
There are 4 rules that you must follow to achieve polymorphism.
You must inherit from the base class.
Your functions must have the same name in every class.
You need the virtual keyword in front of every function, and the override keyword at the end of the child's fonctions.
You have to use a pointer on the main class, and use the "new" keyword to define it as a child type.
See this awesome wiki page for code example.
Hope this is what you wanted. ^^
Yours truly,
SeargX