Необязательные параметры функции: использовать аргументы по умолчанию (NULL) или перегрузить функцию? - PullRequest
40 голосов
/ 01 апреля 2009

У меня есть функция, которая обрабатывает данный вектор, но может также создать сам такой вектор, если он не задан.

Я вижу два варианта дизайна для такого случая, когда параметр функции является необязательным:

Сделать указатель и NULL по умолчанию:

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

Или иметь две функции с перегруженным именем, одна из которых пропускает аргумент:

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
}

Есть ли причины предпочитать одно решение другому?

Я немного предпочитаю второй, потому что я могу сделать вектор ссылкой const, так как он, когда предоставляется, только для чтения, а не для записи. Кроме того, интерфейс выглядит чище (не NULL просто взломать?). И разница в производительности, вызванная косвенным вызовом функции, вероятно, оптимизируется.

Тем не менее, я часто вижу первое решение в коде. Есть ли веские причины, чтобы предпочесть это, кроме лени программиста?

Ответы [ 12 ]

1 голос
/ 01 апреля 2009

Я бы предпочел третий вариант: Разделите на две функции, но не перегружайте.

Перегрузки по природе менее пригодны для использования. Они требуют, чтобы пользователь узнал о двух вариантах и ​​выяснил, в чем разница между ними, и, если они так склонны, также проверил документацию или код, чтобы убедиться, что именно.

У меня была бы одна функция, которая принимает параметр, и тот, который называется «createVectorAndFoo» или что-то в этом роде (очевидно, именование становится легче при реальных проблемах).

Хотя это нарушает правило «две обязанности для функции» (и дает ему длинное имя), я считаю, что это предпочтительнее, когда ваша функция действительно делает две вещи (создать вектор и foo).

0 голосов
/ 01 апреля 2009

Первый способ хуже, потому что вы не можете определить, случайно ли вы передали NULL или это было сделано специально ... если это был несчастный случай, то вы, вероятно, вызвали ошибку.

Со вторым вы можете проверить (утверждать, что угодно) на NULL и обработать его соответствующим образом.

...