[c++] Default parameters with C++ constructors

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?

This question is related to c++ constructor coding-style overloading

The answer is


One thing bothering me with default parameters is that you can't specify the last parameters but use the default values for the first ones. For example, in your code, you can't create a Foo with no name but a given age (however, if I remember correctly, this will be possible in C++0x, with the unified constructing syntax). Sometimes, this makes sense, but it can also be really awkward.

In my opinion, there is no rule of thumb. Personnaly, I tend to use multiple overloaded constructors (or methods), except if only the last argument needs a default value.


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.


One thing bothering me with default parameters is that you can't specify the last parameters but use the default values for the first ones. For example, in your code, you can't create a Foo with no name but a given age (however, if I remember correctly, this will be possible in C++0x, with the unified constructing syntax). Sometimes, this makes sense, but it can also be really awkward.

In my opinion, there is no rule of thumb. Personnaly, I tend to use multiple overloaded constructors (or methods), except if only the last argument needs a default value.


I would go with the default parameters, for this reason: Your example assumes that ctor parameters directly correspond to member variables. But what if that is not the case, and you have to process the parameters before the object is initialize. Having one common ctor would be the best way to go.


Mostly personal choice. However, overload can do anything default parameter can do, but not vice versa.

Example:

You can use overload to write A(int x, foo& a) and A(int x), but you cannot use default parameter to write A(int x, foo& = null).

The general rule is to use whatever makes sense and makes the code more readable.


One more thing to consider is whether or not the class could be used in an array:

foo bar[400];

In this scenario, there is no advantage to using the default parameter.

This would certainly NOT work:

foo bar("david", 34)[400]; // NOPE

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?

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.


I would go with the default parameters, for this reason: Your example assumes that ctor parameters directly correspond to member variables. But what if that is not the case, and you have to process the parameters before the object is initialize. Having one common ctor would be the best way to go.


One thing bothering me with default parameters is that you can't specify the last parameters but use the default values for the first ones. For example, in your code, you can't create a Foo with no name but a given age (however, if I remember correctly, this will be possible in C++0x, with the unified constructing syntax). Sometimes, this makes sense, but it can also be really awkward.

In my opinion, there is no rule of thumb. Personnaly, I tend to use multiple overloaded constructors (or methods), except if only the last argument needs a default value.


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.


If creating constructors with arguments is bad (as many would argue), then making them with default arguments is even worse. I've recently started to come around to the opinion that ctor arguments are bad, because your ctor logic should be as minimal as possible. How do you deal with error handling in the ctor, should somebody pass in an argument that doesn't make any sense? You can either throw an exception, which is bad news unless all of your callers are prepared to wrap any "new" calls inside of try blocks, or setting some "is-initialized" member variable, which is kind of a dirty hack.

Therefore, the only way to make sure that the arguments passed into the initialization stage of your object is to set up a separate initialize() method where you can check the return code.

The use of default arguments is bad for two reasons; first of all, if you want to add another argument to the ctor, then you are stuck putting it at the beginning and changing the entire API. Furthermore, most programmers are accustomed to figuring out an API by the way that it's used in practice -- this is especially true for non-public API's used inside of an organization where formal documentation may not exist. When other programmers see that the majority of the calls don't contain any arguments, they will do the same, remaining blissfully unaware of the default behavior your default arguments impose on them.

Also, it's worth noting that the google C++ style guide shuns both ctor arguments (unless absolutely necessary), and default arguments to functions or methods.


One thing bothering me with default parameters is that you can't specify the last parameters but use the default values for the first ones. For example, in your code, you can't create a Foo with no name but a given age (however, if I remember correctly, this will be possible in C++0x, with the unified constructing syntax). Sometimes, this makes sense, but it can also be really awkward.

In my opinion, there is no rule of thumb. Personnaly, I tend to use multiple overloaded constructors (or methods), except if only the last argument needs a default value.


If creating constructors with arguments is bad (as many would argue), then making them with default arguments is even worse. I've recently started to come around to the opinion that ctor arguments are bad, because your ctor logic should be as minimal as possible. How do you deal with error handling in the ctor, should somebody pass in an argument that doesn't make any sense? You can either throw an exception, which is bad news unless all of your callers are prepared to wrap any "new" calls inside of try blocks, or setting some "is-initialized" member variable, which is kind of a dirty hack.

Therefore, the only way to make sure that the arguments passed into the initialization stage of your object is to set up a separate initialize() method where you can check the return code.

The use of default arguments is bad for two reasons; first of all, if you want to add another argument to the ctor, then you are stuck putting it at the beginning and changing the entire API. Furthermore, most programmers are accustomed to figuring out an API by the way that it's used in practice -- this is especially true for non-public API's used inside of an organization where formal documentation may not exist. When other programmers see that the majority of the calls don't contain any arguments, they will do the same, remaining blissfully unaware of the default behavior your default arguments impose on them.

Also, it's worth noting that the google C++ style guide shuns both ctor arguments (unless absolutely necessary), and default arguments to functions or methods.


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.


Either approach works. But if you have a long list of optional parameters make a default constructor and then have your set function return a reference to this. Then chain the settors.

class Thingy2
{
public:
    enum Color{red,gree,blue};
    Thingy2();

    Thingy2 & color(Color);
    Color color()const;

    Thingy2 & length(double);
    double length()const;
    Thingy2 & width(double);
    double width()const;
    Thingy2 & height(double);
    double height()const;

    Thingy2 & rotationX(double);
    double rotationX()const;
    Thingy2 & rotatationY(double);
    double rotatationY()const;
    Thingy2 & rotationZ(double);
    double rotationZ()const;
}

main()
{
    // gets default rotations
    Thingy2 * foo=new Thingy2().color(ret)
        .length(1).width(4).height(9)
    // gets default color and sizes
    Thingy2 * bar=new Thingy2()
        .rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
    // everything specified.
    Thingy2 * thing=new Thingy2().color(ret)
        .length(1).width(4).height(9)
        .rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
}

Now when constructing the objects you can pick an choose which properties to override and which ones you have set are explicitly named. Much more readable :)

Also, you no longer have to remember the order of the arguments to the constructor.


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.


Mostly personal choice. However, overload can do anything default parameter can do, but not vice versa.

Example:

You can use overload to write A(int x, foo& a) and A(int x), but you cannot use default parameter to write A(int x, foo& = null).

The general rule is to use whatever makes sense and makes the code more readable.


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.


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.


If creating constructors with arguments is bad (as many would argue), then making them with default arguments is even worse. I've recently started to come around to the opinion that ctor arguments are bad, because your ctor logic should be as minimal as possible. How do you deal with error handling in the ctor, should somebody pass in an argument that doesn't make any sense? You can either throw an exception, which is bad news unless all of your callers are prepared to wrap any "new" calls inside of try blocks, or setting some "is-initialized" member variable, which is kind of a dirty hack.

Therefore, the only way to make sure that the arguments passed into the initialization stage of your object is to set up a separate initialize() method where you can check the return code.

The use of default arguments is bad for two reasons; first of all, if you want to add another argument to the ctor, then you are stuck putting it at the beginning and changing the entire API. Furthermore, most programmers are accustomed to figuring out an API by the way that it's used in practice -- this is especially true for non-public API's used inside of an organization where formal documentation may not exist. When other programmers see that the majority of the calls don't contain any arguments, they will do the same, remaining blissfully unaware of the default behavior your default arguments impose on them.

Also, it's worth noting that the google C++ style guide shuns both ctor arguments (unless absolutely necessary), and default arguments to functions or methods.


One more thing to consider is whether or not the class could be used in an array:

foo bar[400];

In this scenario, there is no advantage to using the default parameter.

This would certainly NOT work:

foo bar("david", 34)[400]; // NOPE

Matter of style, but as Matt said, definitely consider marking constructors with default arguments which would allow implicit conversion as 'explicit' to avoid unintended automatic conversion. It's not a requirement (and may not be preferable if you're making a wrapper class which you want to implicitly convert to), but it can prevent errors.

I personally like defaults when appropriate, because I dislike repeated code. YMMV.


Either approach works. But if you have a long list of optional parameters make a default constructor and then have your set function return a reference to this. Then chain the settors.

class Thingy2
{
public:
    enum Color{red,gree,blue};
    Thingy2();

    Thingy2 & color(Color);
    Color color()const;

    Thingy2 & length(double);
    double length()const;
    Thingy2 & width(double);
    double width()const;
    Thingy2 & height(double);
    double height()const;

    Thingy2 & rotationX(double);
    double rotationX()const;
    Thingy2 & rotatationY(double);
    double rotatationY()const;
    Thingy2 & rotationZ(double);
    double rotationZ()const;
}

main()
{
    // gets default rotations
    Thingy2 * foo=new Thingy2().color(ret)
        .length(1).width(4).height(9)
    // gets default color and sizes
    Thingy2 * bar=new Thingy2()
        .rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
    // everything specified.
    Thingy2 * thing=new Thingy2().color(ret)
        .length(1).width(4).height(9)
        .rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
}

Now when constructing the objects you can pick an choose which properties to override and which ones you have set are explicitly named. Much more readable :)

Also, you no longer have to remember the order of the arguments to the constructor.


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.


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.


Matter of style, but as Matt said, definitely consider marking constructors with default arguments which would allow implicit conversion as 'explicit' to avoid unintended automatic conversion. It's not a requirement (and may not be preferable if you're making a wrapper class which you want to implicitly convert to), but it can prevent errors.

I personally like defaults when appropriate, because I dislike repeated code. YMMV.


Either approach works. But if you have a long list of optional parameters make a default constructor and then have your set function return a reference to this. Then chain the settors.

class Thingy2
{
public:
    enum Color{red,gree,blue};
    Thingy2();

    Thingy2 & color(Color);
    Color color()const;

    Thingy2 & length(double);
    double length()const;
    Thingy2 & width(double);
    double width()const;
    Thingy2 & height(double);
    double height()const;

    Thingy2 & rotationX(double);
    double rotationX()const;
    Thingy2 & rotatationY(double);
    double rotatationY()const;
    Thingy2 & rotationZ(double);
    double rotationZ()const;
}

main()
{
    // gets default rotations
    Thingy2 * foo=new Thingy2().color(ret)
        .length(1).width(4).height(9)
    // gets default color and sizes
    Thingy2 * bar=new Thingy2()
        .rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
    // everything specified.
    Thingy2 * thing=new Thingy2().color(ret)
        .length(1).width(4).height(9)
        .rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
}

Now when constructing the objects you can pick an choose which properties to override and which ones you have set are explicitly named. Much more readable :)

Also, you no longer have to remember the order of the arguments to the constructor.


I would go with the default parameters, for this reason: Your example assumes that ctor parameters directly correspond to member variables. But what if that is not the case, and you have to process the parameters before the object is initialize. Having one common ctor would be the best way to go.


If creating constructors with arguments is bad (as many would argue), then making them with default arguments is even worse. I've recently started to come around to the opinion that ctor arguments are bad, because your ctor logic should be as minimal as possible. How do you deal with error handling in the ctor, should somebody pass in an argument that doesn't make any sense? You can either throw an exception, which is bad news unless all of your callers are prepared to wrap any "new" calls inside of try blocks, or setting some "is-initialized" member variable, which is kind of a dirty hack.

Therefore, the only way to make sure that the arguments passed into the initialization stage of your object is to set up a separate initialize() method where you can check the return code.

The use of default arguments is bad for two reasons; first of all, if you want to add another argument to the ctor, then you are stuck putting it at the beginning and changing the entire API. Furthermore, most programmers are accustomed to figuring out an API by the way that it's used in practice -- this is especially true for non-public API's used inside of an organization where formal documentation may not exist. When other programmers see that the majority of the calls don't contain any arguments, they will do the same, remaining blissfully unaware of the default behavior your default arguments impose on them.

Also, it's worth noting that the google C++ style guide shuns both ctor arguments (unless absolutely necessary), and default arguments to functions or methods.


Matter of style, but as Matt said, definitely consider marking constructors with default arguments which would allow implicit conversion as 'explicit' to avoid unintended automatic conversion. It's not a requirement (and may not be preferable if you're making a wrapper class which you want to implicitly convert to), but it can prevent errors.

I personally like defaults when appropriate, because I dislike repeated code. YMMV.


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?

Matter of style, but as Matt said, definitely consider marking constructors with default arguments which would allow implicit conversion as 'explicit' to avoid unintended automatic conversion. It's not a requirement (and may not be preferable if you're making a wrapper class which you want to implicitly convert to), but it can prevent errors.

I personally like defaults when appropriate, because I dislike repeated code. YMMV.


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.


I would go with the default parameters, for this reason: Your example assumes that ctor parameters directly correspond to member variables. But what if that is not the case, and you have to process the parameters before the object is initialize. Having one common ctor would be the best way to go.


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?

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.


Either approach works. But if you have a long list of optional parameters make a default constructor and then have your set function return a reference to this. Then chain the settors.

class Thingy2
{
public:
    enum Color{red,gree,blue};
    Thingy2();

    Thingy2 & color(Color);
    Color color()const;

    Thingy2 & length(double);
    double length()const;
    Thingy2 & width(double);
    double width()const;
    Thingy2 & height(double);
    double height()const;

    Thingy2 & rotationX(double);
    double rotationX()const;
    Thingy2 & rotatationY(double);
    double rotatationY()const;
    Thingy2 & rotationZ(double);
    double rotationZ()const;
}

main()
{
    // gets default rotations
    Thingy2 * foo=new Thingy2().color(ret)
        .length(1).width(4).height(9)
    // gets default color and sizes
    Thingy2 * bar=new Thingy2()
        .rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
    // everything specified.
    Thingy2 * thing=new Thingy2().color(ret)
        .length(1).width(4).height(9)
        .rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
}

Now when constructing the objects you can pick an choose which properties to override and which ones you have set are explicitly named. Much more readable :)

Also, you no longer have to remember the order of the arguments to the constructor.


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?

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.


Mostly personal choice. However, overload can do anything default parameter can do, but not vice versa.

Example:

You can use overload to write A(int x, foo& a) and A(int x), but you cannot use default parameter to write A(int x, foo& = null).

The general rule is to use whatever makes sense and makes the code more readable.


Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to constructor

Two constructors Class constructor type in typescript? ReactJS: Warning: setState(...): Cannot update during an existing state transition Inheritance with base class constructor with parameters What is the difference between using constructor vs getInitialState in React / React Native? Getting error: ISO C++ forbids declaration of with no type undefined reference to 'vtable for class' constructor Call asynchronous method in constructor? Purpose of a constructor in Java? __init__() missing 1 required positional argument

Examples related to coding-style

Method Call Chaining; returning a pointer vs a reference? 80-characters / right margin line in Sublime Text 3 Cannot find reference 'xxx' in __init__.py - Python / Pycharm How to stick <footer> element at the bottom of the page (HTML5 and CSS3)? Simple way to create matrix of random numbers Is calling destructor manually always a sign of bad design? Count all values in a matrix greater than a value Iterate through a C++ Vector using a 'for' loop Which comment style should I use in batch files? Dictionaries and default values

Examples related to overloading

What is the difference between dynamic and static polymorphism in Java? TypeScript function overloading Constructor overload in TypeScript What is the difference between method overloading and overriding? Differentiate between function overloading and function overriding How do I use method overloading in Python? How can I create a Java method that accepts a variable number of arguments? Python function overloading PHP function overloading What is function overloading and overriding in php?