User Tools

Site Tools


static-type-default-arguments-cpp

Static type and default arguments in C++

Quiz. What does this program output?

#include <iostream>
 
class Vehicle
{
public:
  virtual void FillUp(int amount = 20)
  {
      std::cout << "Filling up the vehicle with " << amount << " gallons of gas" << std::endl;
  };
};
 
class Car : public Vehicle
{
public:
  virtual void FillUp(int amount = 10)
  {
    std::cout << "Filling up the car with " << amount << " gallons of gas" << std::endl;
  };
};
 
int main(void)
{
  Vehicle *v = new Car;
 
  v->FillUp();
 
  return 0;
}

If you thought the output would be “Filling up the car with 10 gallons of gas”, you're in good company, but you're still mistaken. The output is actually “Filling up the car with 20 gallons of gas”.

But how can that be? It is as if a totally new, fictitious method, mashed together from pieces of Vehicle's FillUp method and Car's FillUp method was called.

But it is what the C++ standard demands. Many C++ programmers are not aware that in some situations you need to be aware that objects are actually not of one type, but of two types, a dynamic type and a static type. One such situation is changing default arguments in overridden methods.

Let's step back for a second. What is a static type?

int a;

a is an object and is of the static type int. Easy.

[...Vehicle and Car defined as above...]
 
int main(void)
{
  Vehicle v;
  Car c;
 
  v = c;
 
  v.FillUp();
}

This is legal C++. The car c is “sliced” to a vehicle and assigned to v. v is of the static type Vehicle.

Everybody expects the output to be “Filling up the vehicle with 20 gallons of gas” and would be right.

Now, the tricky part.

[...Vehicle and Car defined as above...]
 
int main(void)
{
  Vehicle *v = new Car;
 
  v->FillUp();
 
  return 0;
}

In this example where v is a pointer, v is still of the static type Vehicle, but of the dynamic type Car.

Method dispatch in C++ works on the dynamic type, so Car's FillUp method is selected.

But for performance reasons the C++ designers decided that the default arguments to a method are selected and bound at compile time and according to the static type.

And that is why the shocked intuition that two methods were being mashed together is actually correct. The method body from the child class is selected, but the default arguments from the parent class are used.

static-type-default-arguments-cpp.txt · Last modified: 2018-06-23 11:48 by Thomas Hühn