I am just testing with virtual keyword and inheritance concepts in c++. I have written a small program:
#include<stdio.h>
#include<iostream>
using namespace std;
class cna_MO
{
public:
virtual void print()
{
cout << "cna_MO" << endl;
}
};
class cna_bsc:public cna_MO
{
public:
void print()
{
cna_MO::print();
}
void print(int a)
{
cout << "cna_BSC" << endl;
}
};
class cna_Mo
{
cna_MO *_mo;
public:
cna_Mo()
{
_mo = new cna_bsc;
}
virtual void print(int a)
{
cout << "cna_Mo with arg" << endl;
_mo->print(5);
}
virtual void print()
{
cout << "cna_Mo" << endl;
_mo->print();
}
};
int main()
{
cna_Mo valid_mo;
cout << "old case is started" << endl;
valid_mo.print();
cout << "new case is started" << endl;
valid_mo.print(5);
return 0;
}
What I have done here is I have overloaded a virtual function in parent class in child class! Is this not the right thing to do?
I am getting the compilation errors as below:
"temp10.cc", line 45: Error: Too many arguments in call to "cna_MO::print()".
When you have a function with same name and different parameters in the derived class as that of the base class, then that function will be hidden. You can find more info here..
You can call the specific hidden function by calling like
Base::hiddenFun();
Once you overload a function from Base class in Derived class all functions with the same name in the Base class get hidden in Derived class.
Once you added the function
cna_bsc::print(int a)
to your derived class the functioncna_MO::::print()
is no longer visible to users of the Derived class. This is known as function hiding.Solution: In order to make the hidden function visible in derived class, You need to add:
in the
public
section of your derived classcna_bsc
.Good Read:
What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?
If you REALLY MUST do it like this, i.e. have a pointer to one class and initialise as a derived class, there's no choice but to always cast the pointer to the correct type when using it. In this case,
((cna_bsc*)_mo)->print(5);
That can't work because given a
cna_MO *
, you can see at compile-time that the pointed object does not (necessarily) have the int overload. If it actually pointed to a base-class object,_mo->print(5);
would really have nothing to call. Also there can be an infinite number of (not yet implemented) derived classes that don't have to support this call.Every derived class must have
print(int)
- declare it in the base class.Every derived class need not have
print(int)
-cna_Mo
only works withcna_bsc
, so the member should becna_bsc* _mo
.Ideally your print that takes an int should have a different name but given you want both functions to be called print, you should make them both non-virtual and make them call protected virtual functions.
It's because the print function in the child class takes a parameter and the original doesn't.
in cna_MO (parent class):
in cna_bsc (child class):
Basically the child's print should not take an int argument:
EDIT:
Maybe the best would be to make passing the int optional ?
eg:
in cna_MO (parent class):
in cna_bsc (child class):
so if a == -1 you can probably assume, they didn't pass anything.
The trick is that both the parent and child need the same method siganture, meaning same return type and the same argument types.