Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolution of virtual function with default parameters [duplicate]

header.h

#include <iostream>
using namespace std;
class A
{
    public:
        virtual void display(int i=5) { cout<< "Base::" << i << endl; }
};

class B : public A
{
    public:
        void display(int i=9) { cout<< "Derived::" << i << endl; }
};  

source.h

#include <iostream>
#include "header.h"
using namespace std;
int main()
{
    A * a = new B();
    a->display();

    A* aa = new A();
    aa->display();

    B* bb = new B();
    bb->display();
}  

output

Derived::5
Base::5
Derived::9  

My understanding was default parameter functions were resolved during compile time using function overloading. Virtual functions were then resolved during runtime using function overriding.

But what is happening is a mess.
How does the function resolution actually happen here?

like image 517
cppcoder Avatar asked Sep 23 '14 12:09

cppcoder


People also ask

What will happen if a virtual function has any default value parameter?

Default Arguments are the values provided during function declaration, such that values can be automatically assigned if no argument is passed to them. In case any value is passed the default value is overridden and it becomes a parameterized argument.

Can a pure virtual function have default parameters?

Yes, C++ virtual functions can have default parameters.

Which case default argument passing in function is not allowed?

Default arguments are only allowed in the parameter lists of function declarations and lambda-expressions, (since C++11) and are not allowed in the declarations of pointers to functions, references to functions, or in typedef declarations.

Which of the following function types of function Cannot have default parameters?

Constructors cannot have default parameters.


2 Answers

Your code is actually seen by the compiler like this:
(The display() method is not actually there, but the resolving works in similar way)

class A
{
public:
    virtual void display(int i) { cout<< "Base::" << i << endl; }
    void display() { display(5); }
};

class B : public A
{
public:
    void display(int i) override { cout<< "Derived::" << i << endl; }
    void display() { display(9); }
};

Now you should understand what happens. You are calling the non-virtual display() which calls the virtual function. In more strict words: the default argument is resolved just like if the no-arg non-virtual method was there - by the type of the variable (not by the actual type of the object), but the code gets executed according to real object type, because it is virtual method:

int main()
{
    A * a = new B(); // type of a is A*   real type is B
    a->display();    // calls A::display() which calls B::display(5)

    A* aa = new A(); // type of aa is A*  real type is A
    aa->display();   // calls A::display() which calls A::display(5)

    B* bb = new B(); // type of bb is B*  real type is B
    bb->display();   // calls B::display() which calls B::display(9)
}  
like image 174
firda Avatar answered Sep 23 '22 14:09

firda


There is no polymorphism on default arguments. They are resolved compile-time.

A::display has default argument equal 5. B::display has default argument equal 9. It's only the type of a, aa, bb variables that matters.

Use of different default arguments in polymorphic methods is confusing and should be avoided.

like image 37
0xF Avatar answered Sep 24 '22 14:09

0xF