I was asked this question in an interview. I was not able to answer this there. Neither am I able to get it now, as to why the output is the way it is. Here is the code:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void fun ( int x = 0)
{
cout << "Base::fun(), x = " << x << endl;
}
};
class Derived : public Base
{
public:
virtual void fun ( float x = 10.0 )
{
cout << "Derived::fun(), x = " << x << endl;
}
};
int main()
{
Derived d1;
Base *bp = &d1;
bp->fun();
d1.fun();
d1.fun(1.2);
return 0;
}
The output of the above code is:
Base::fun(), x = 0
Derived::fun(), x = 10
Derived::fun(), x = 1.2
The problem is: In the first case we say that both the fun() functions get overloaded (and not overridden since they differ in their declarations) and the base fun() gets called, but it is not possible for these declarations of fun() to be overloaded (since they differ only whether the declaration contains default argument or not)
void fun(int x = 0)
void fun(float x = 10.0)
It is not possible for these functions to get overloaded.
There seems to be a contradiction in both the above cases.
Any related article/ link explaining the situation would be highly helpful.
In C++, for a member function to override a base class function, the argument types have to exactly match the base class function's argument types. Since the base class function takes in an int
and your derived class's function takes in a float
, it's not considered an override. You can see this by using the override
keyword:
class Base
{
public:
virtual void fun ( int x = 0)
{
cout << "Base::fun(), x = " << x << endl;
}
};
class Derived : public Base
{
public:
virtual void fun ( float x = 10.0 ) override // Doesn't compile!
{
cout << "Derived::fun(), x = " << x << endl;
}
};
What's happening in your code is that C++ considers your function to be an overload (another function with the same name) rather than an override. Let's look at this code:
Derived d1;
Base *bp = &d1;
bp->fun();
Here, since the line bp->fun()
uses a call through a base class pointer, C++ looks in Base
to see which function to call. It finds Base::fun(int)
. Now, since that function is marked virtual
, it will call Base::fun(int)
unless something overrode it. But since there isn't an override, Base::fun(int)
ends up getting invoked.
So what about these later two lines?
d1.fun();
d1.fun(1.2);
Here, since you're calling these functions on objects of static type Derived
, C++ tries to find a function called fun
in the Derived
class. It finds your new function Derived::fun(float)
, and due to the way C++ does name lookup in classes it does not look in the base class to find Base::fun(int)
. Therefore, both of these calls are treated as calls to Derived::fun(float)
, so there's no ambiguity about which function to call when no arguments are presented. The compiler never even looked in the Base
type because there was no need to.
So, to summarize:
fun
through the base pointer looks for a function named fun
taking in an int
, since the base pointer's fun
function takes in an int
. That finds the version in Base
because there's no oerride.fun
through the derived object looks for a function named fun
starting in Derived
, and it finds your override.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With