views:

110

answers:

5

At my workplace, usually default parameters are specified in the declaration.What is the normal custom? Should I specify default parameters in method declaration or method definition?

EDIT: Is there any way to specify default parameters for references?

EDIT: Can someone please provide an example of default arguments for reference parameters?

+6  A: 

Method declaration. The caller probably doesn't have the definition, but default parameters must be known at the call place.

ybungalobill
And yes, default parameters for references work the same way as other default parameters.
moala
A: 

I used to make use of default values, but meanwhile I changed my mind: I find the code better readable when I write the parameter values explictly. Sometimes I define another method like the following:

bool Initialize( const char * pszPath );
bool InitializeDefault();

instead of

bool Initialize( const char * pszOptPath = NULL );
ur
The first sentence is incorrect. But in practice the calling code may not see the definition. Default parameters must be specified in code that the calling code sees, in order to be useful to the calling code.
Alf P. Steinbach
@Alf: Is specifying a default value at function definition (in the .cpp file) of any practical use?
ur
@Alf: See Bjarne at http://www2.research.att.com/~bs/glossary.html#Gdefault-argument "default argument - a value specified for an argument in a function declaration, to be used if a call of the function doesn't specify a value for that argument. This is commonly used to allow a simple interface for common uses while making it easy to use less common facilities by specifying more arguments."
ur
@ur: I can't think of any example where it would be useful to define default parameters in a method implementation in a separately compiled file, but perhaps in some corner case. However, for a header-only module it can be reasonable to define methods inline in the class. And of course you can define default parameters in such a definition. :-)
Alf P. Steinbach
@ur: regarding Bjarne (EDIT: your comment read just "See Bjarne at" when I wrote this), Facebook keeps giving me the same advice, but I can't imagine that he'd be interested in all the music video links I'm posting there, so I think it's just a fixed idea that Facebook has. :-)
Alf P. Steinbach
@ur: What Bjarne says is just an accepted practice based on common-sense. Formally, you can specify default arguments anywhere. You can actually scatter them across multiple declarations.
AndreyT
+3  A: 

ybungalobill has already answered the question about where.

Regarding references, for a reference to const T you can just specify a default value directly.

For a reference to non-const you need to specify the default "value" as a reference to non-const. This might be a global, or an instance of a class with suitable conversion. E.g.,

#include <iostream>

struct DummyInt
{
    int dummy;
    operator int& () { return dummy; }
    DummyInt(): dummy( 0 ) {}
};

void foo( int& v = DummyInt() ) {}  // Whatever

int main()
{
    int x   = 42;
    foo( x );
    foo();
}

Cheers & hth.,

– Alf

Alf P. Steinbach
Thanks, just what I was looking for.
nakiya
Is you example potentially dangerous? If the parameter `v` were used in the function body wouldn't the lifetime of the `DummyInt` and hence the contained `dummy` have ended by the time that the function body had been entered? I know that temporaries can have their lifetime extended if they are bound to `const` references but I didn't think that this rule or anything like it held here.
Charles Bailey
How to use default parameters for non-const references then?
nakiya
@Alf P. Steinbach:Do I need to define one struct per each default parameter like this one? btw, You are missing couple of parantheses after DummyInt()
nakiya
No, the example isn't potentially dangerous (lifetime of the temporary extends through the full-expression of the call), and no, there are no missing parentheses. :-)
Alf P. Steinbach
nakiya
@Alf P. Steinbach: Oh yes, of course. I see now. I fell (again) into the trap that I already know about!
Charles Bailey
Regarding "one struct per each default parameter", no that's not necessary, not even one struct per type. You can just make that a class template. However, it's the kind of neat thing that's rarely if ever used except as an example of neatness...
Alf P. Steinbach
@nakita: regarding "missing parentheses", they're not necessary because `DummyInt` provides an implicit conversion. Tip: when you want to check standard-conformance of some C++ code, try Comeau Online (it's free). There's no guarantee of course, but Comeau is about the most conforming compiler on mother Earth, it's Very Good.
Alf P. Steinbach
g++ throws an error actually. And I think the syntax is clearer if you add those parens. :D. But, that's a minor thing
nakiya
@nakiya: the code compiled fine with g++ 4.4.1, msvc 10.0 and comeau online before I posted it. Not to mention that it's trivial code. Which version of g++ are you using, and with what options?
Alf P. Steinbach
A: 

Must be at method declaration, so that the caller can know what is exactly expected by the function.
You can do tricks like Alf says but not sure why is it needed. May be you want to take a look at your design of function.

Manoj R
+1  A: 

Well, the normal practice is to have the same set of default arguments for all translation units. In order to achieve that you obviously have to specify the default arguments in the declaration of the function in the header file.

As for default argument of reference parameter... of course, it is possible. For example

extern int i;

void foo(int &r = i);
void bar(const double &r = 0);
AndreyT
`Well, the normal practice is to have the default arguments to be the same for all translation units.` What doess this mean? :D. And, I have to define `i` somewhere else. :(
nakiya