default parameters in .h and .cpp files

sudeepdino008 picture sudeepdino008 · Feb 15, 2013 · Viewed 52.6k times · Source

COMPILER: g++ 4.7.2

Ok. So I am confused about default parameters in .h and .cpp files. It is mentioned in many places( including this site) that default parameters can be added only in .h files and not in .cpp files. However, this code proves it wrong:

test1.h

#pragma once

#include <iostream>
using namespace std;

class Class{
public:
    Class(int, int, int=1);
};

test1.cpp

#include "test1.h"

Class::Class(int a, int b=2, int c)
{
    cout<<a<<" "<<b<<" "<<c<<endl;
}

int main()
{
    Class a(1);
    return 0;
}

Now, according to what I have tested, default parameters can be added to .cpp files. However, the following restrictions hold:

  1. The default parameters present in .cpp and .h file should not overlap. i.e. Class(a, b, c=1) (in .h file) and Class::Class(a,b,c=2)( in .cpp file) is invalid.

    It is a well known rule that once default parameters have been added, all the variables declared after that must also contain default values. Lets call this the defpara rule. Now,

  2. The variables stated in the function declaration( .h file) should obey the defpara rule i.e. Class(a, b=2, c) (in .h file) is invalid irrespective of what's declared in .cpp file.

  3. If one considers the variables having default values (as an intersection of default values in .h and .cpp files), it would follow the defpara rule. i.e. Class(a, b, c=1) (in .h file) and Class::Class(a,b=2,c)( in .cpp file) is valid. But Class(a, b, c=1) (in .h file) and Class::Class(a=2,b,c)( in .cpp file) is invalid.

So....I am right, wrong???

Answer

Mats Petersson picture Mats Petersson · Feb 15, 2013

Defaults should always go in the header file, if the function is declared in a header file.

This is because the compiler will use the header file for ALL compile units that use your class [unless you are being "naughty" and don't use the header file everywhere it should go].

Since the compiler adds default arguments when it compiles the code that CALLS the function (in this case the constructor), it won't matter what the defaults are in the .cpp file.

Of course, in this case, there are only one "user" of the headerfile, and only one place where the constructor is called. But having defaults in the .cpp file is generally wrong [unless it's a local function].

You get very "interesting" bugs if you "mix" defaults - e.g. if your .cpp has one default, and the headefile a different one. If you are really skilled, you can even get the compiler to generate different defaults for different calls to the function, which will almost certainly lead to some headscratching if the code relies on the default being some particular value. And don't be tempted to copy the defaults from the header to the .cpp file "just to make it easier to see". If someone ever changes the default, then it's almost certainly either not going to change in both places, and possibly worse: change the wrong defaults, so it doesn't do what was intended.