tags:

views:

132

answers:

3

I have an existing method (or function in general) which I need to grow additional functionality, but I don't want to break any use of the method elsewhere in the code. Example:

int foo::bar(int x)
{
 // a whole lot of code here
 return 2 * x + 4;
}

is widely used in the codebase. Now I need to make the 4 into a parameter, but any code that already calls foo::bar should still receive what it expects. Should I extend and rename the old method and wrap it into a new one like

int foo::extended_bar(int x, int y)
{
 // ...
 return 2 * x + y;
}

int foo::bar(int x)
{
 return extended_bar(x,4);
}

or should I declare a default argument in the header file like

int bar(int x, int y=4);

and just extend the function

int foo::bar(int x, int y)
{
 // ...
 return 2 * x + y;
}

What are advantages and disadvantages of each variant?

+4  A: 

I usually use a wrapper function (via overloading most of the time) instead of default parameters.

The reason is that there are two levels of backward compatibility:

  1. Having source-level backward compatibility means that you have to recompile the calling code without changes, because the new function signatures are compatible to the old ones. This level can be achieved with both; default values and wrappers/overloading.

  2. A stronger level is binary-level backward compatibility, which even works without recompilation, e.g. when you don't have access to the calling code. Imagine you deploy your function in binary form, like in a DLL, etc. In such a case, the signatures have the be exactly the same to make it work, which is not the case for default values - they will break this level of compatibility.

Another advantage of wrapper functions is - if your application has logging of any kind - you can dump out a warning in the old function that it will become obsolete in future versions and that it is recommended to use the new one.

beef2k
A: 

The longer I use C++, the less I like default function parameters. I can't pinpoint any specific reason for my dislike, but I find that if I use them, I almost always end up removing them later. So my (subjective) vote goes for the new named function - the name could of course be same as that of the old one.

anon
A: 

I personally believe that implicit behaviors are (one of) the roots of all evil.

Anything that obfuscates for a maintainer or caller the identity of the target being invoked should have a very strong justification, especially if it is part of a major API.

Therefore, I would argue strongly against the option with the default operation.

In addition, I believe that if a certain function can be invoked with a different number of parameters, then there is something inherently different both versions of the function or they are doing too much. The distinction should probably be in the name, and should probably be more meaningful than "_extended"

Uri
I agree on your last paragraph, it should rather be bar_with_adjustable_summand(x,y) or the like. But what would be the solution concerning your first problem, if I need to control an additional parameter in an otherwise unchanged function?
balpha