Default parameters with C++ constructors

269,363

Solution 1

Definitely a matter of style. I prefer constructors with default parameters, so long as the parameters make sense. Classes in the standard use them as well, which speaks in their favor.

One thing to watch out for is if you have defaults for all but one parameter, your class can be implicitly converted from that parameter type. Check out this thread for more info.

Solution 2

I'd go with the default arguments, especially since C++ doesn't let you chain constructors (so you end up having to duplicate the initialiser list, and possibly more, for each overload).

That said, there are some gotchas with default arguments, including the fact that constants may be inlined (and thereby become part of your class' binary interface). Another to watch out for is that adding default arguments can turn an explicit multi-argument constructor into an implicit one-argument constructor:

class Vehicle {
public:
  Vehicle(int wheels, std::string name = "Mini");
};

Vehicle x = 5;  // this compiles just fine... did you really want it to?

Solution 3

This discussion apply both to constructors, but also methods and functions.

Using default parameters?

The good thing is that you won't need to overload constructors/methods/functions for each case:

// Header
void doSomething(int i = 25) ;

// Source
void doSomething(int i)
{
   // Do something with i
}

The bad thing is that you must declare your default in the header, so you have an hidden dependancy: Like when you change the code of an inlined function, if you change the default value in your header, you'll need to recompile all sources using this header to be sure they will use the new default.

If you don't, the sources will still use the old default value.

using overloaded constructors/methods/functions?

The good thing is that if your functions are not inlined, you then control the default value in the source by choosing how one function will behave. For example:

// Header
void doSomething() ;
void doSomething(int i) ;

// Source

void doSomething()
{
   doSomething(25) ;
}

void doSomething(int i)
{
   // Do something with i
}

The problem is that you have to maintain multiple constructors/methods/functions, and their forwardings.

Solution 4

In my experience, default parameters seem cool at the time and make my laziness factor happy, but then down the road I'm using the class and I am surprised when the default kicks in. So I don't really think it's a good idea; better to have a className::className() and then a className::init(arglist). Just for that maintainability edge.

Solution 5

Sam's answer gives the reason that default arguments are preferable for constructors rather than overloading. I just want to add that C++-0x will allow delegation from one constructor to another, thereby removing the need for defaults.

Share:
269,363
Rob
Author by

Rob

C++, MFC, Win32, WTL, STL, Boost, HTML, CSS, JavaScript, Qt, Python, jQuery Mobile.

Updated on February 07, 2020

Comments

  • Rob
    Rob about 4 years

    Is it good practice to have a class constructor that uses default parameters, or should I use separate overloaded constructors? For example:

    // Use this...
    class foo  
    {
    private:
        std::string name_;
        unsigned int age_;
    public:
        foo(const std::string& name = "", const unsigned int age = 0) :
            name_(name),
            age_(age)
        {
            ...
        }
    };
    
    // Or this?
    class foo  
    {
    private:
        std::string name_;
        unsigned int age_;
    public:
        foo() :
        name_(""),
        age_(0)
    {
    }
    
    foo(const std::string& name, const unsigned int age) :
            name_(name),
            age_(age)
        {
            ...
        }
    };
    

    Either version seems to work, e.g.:

    foo f1;
    foo f2("Name", 30);
    

    Which style do you prefer or recommend and why?

  • Denilson Sá Maia
    Denilson Sá Maia over 12 years
    In that case, add the "explicit" keyword to the constructor. It should prevent Vehicle x = 5; from compiling.
  • mskfisher
    mskfisher almost 11 years
    And now, 5 years later, C++11 has added delegating constructors and default member initialization in the class definition, making the default parameter workaround unnecessary: en.wikipedia.org/wiki/C%2B%2B11#Object_construction_improvem‌​ent
  • WillC
    WillC over 5 years
    I like this ability to chain settors; whether at instantiation or for later updates. Have you ever tried accepting a struct and picking the attributes out of that into the object - or just using the struct as the data retainer within the object?