Optional function parameters: Use default argument

2019-01-16 15:55发布

I have a function that processes a given vector, but may also create such a vector itself if it is not given.

I see two design choices for such a case, where a function parameter is optional:

Make it a pointer and make it NULL by default:

void foo(int i, std::vector<int>* optional = NULL) {
  if(optional == NULL){
    optional = new std::vector<int>();
    // fill vector with data
  }
  // process vector
}

Or have two functions with an overloaded name, one of which leaves out the argument:

void foo(int i) {
   std::vector<int> vec;
   // fill vec with data
   foo(i, vec);
}

void foo(int i, const std::vector<int>& optional) {
  // process vector
}

Are there reasons to prefer one solution over the other?

I slightly prefer the second one because I can make the vector a const reference, since it is, when provided, only read, not written. Also, the interface looks cleaner (isn't NULL just a hack?). And the performance difference resulting from the indirect function call is probably optimized away.

Yet, I often see the first solution in code. Are there compelling reasons to prefer it, apart from programmer laziness?

12条回答
地球回转人心会变
2楼-- · 2019-01-16 16:31

While I do understand the complaints of many people regarding default parameters and overloads, there seems to be a lack of understanding to the benefits that these features provide.

Default Parameter Values:
First I want to point out that upon initial design of a project, there should be little to no use for defaults if well designed. However, where defaults' greatest assets comes into play is with existing projects and well established APIs. I work on projects that consist of millions of existing lines of code and do not have the luxury to re-code them all. So when you wish to add a new feature which requires an extra parameter; a default is needed for the new parameter. Otherwise you will break everyone that uses your project. Which would be fine with me personally, but I doubt your company or users of your product/API would appreciate having to re-code their projects on every update. Simply, Defaults are great for backwards compatibility! This is usually the reason you will see defaults in big APIs or existing projects.

Function Overrides: The benefit of function overrides is that they allow for the sharing of a functionality concept, but with with different options/parameters. However, many times I see function overrides lazily used to provide starkly different functionality, with just slightly different parameters. In this case they should each have separately named functions, pertaining to their specific functionality (As with the OP's example).

These, features of c/c++ are good and work well when used properly. Which can be said of most any programming feature. It is when they are abused/misused that they cause problems.

Disclaimer:
I know that this question is a few years old, but since these answers came up in my search results today (2012), I felt this needed further addressing for future readers.

查看更多
疯言疯语
3楼-- · 2019-01-16 16:36

I would definitely favour the 2nd approach of overloaded methods.

The first approach (optional parameters) blurs the definition of the method as it no longer has a single well-defined purpose. This in turn increases the complexity of the code, making it more difficult for someone not familiar with it to understand it.

With the second approach (overloaded methods), each method has a clear purpose. Each method is well-structured and cohesive. Some additional notes:

  • If there's code which needs to be duplicated into both methods, this can be extracted out into a separate method and each overloaded method could call this external method.
  • I would go a step further and name each method differently to indicate the differences between the methods. This will make the code more self-documenting.
查看更多
姐就是有狂的资本
4楼-- · 2019-01-16 16:36

I agree, I would use two functions. Basically, you have two different use cases, so it makes sense to have two different implementations.

I find that the more C++ code I write, the fewer parameter defaults I have - I wouldn't really shed any tears if the feature was deprecated, though I would have to re-write a shed load of old code!

查看更多
forever°为你锁心
5楼-- · 2019-01-16 16:39

I usually avoid the first case. Note that those two functions are different in what they do. One of them fills a vector with some data. The other doesn't (just accept the data from the caller). I tend to name differently functions that actually do different things. In fact, even as you write them, they are two functions:

  • foo_default (or just foo)
  • foo_with_values

At least I find this distinction cleaner in the long therm, and for the occasional library/functions user.

查看更多
聊天终结者
6楼-- · 2019-01-16 16:41

I, too, prefer the second one. While there are not much difference between the two, you are basically using the functionality of the primary method in the foo(int i) overload and the primary overload would work perfectly without caring about existence of lack of the other one, so there is more separation of concerns in the overload version.

查看更多
Animai°情兽
7楼-- · 2019-01-16 16:43

The first way is poorer because you cannot tell if you accidentally passed in NULL or if it was done on purpose... if it was an accident then you have likely caused a bug.

With the second one you can test (assert, whatever) for NULL and handle it appropriately.

查看更多
登录 后发表回答