Подтвердить что ты не робот

Неправильно ли перегружать функцию, чтобы взять как указатель, так и ссылку?

Например, если у меня была структура FooSpec:

struct FooSpec { /* lots of data */ };

Неправильно ли использовать обе следующие функции в качестве перегруженных функций? Или я должен просто выбрать один и придерживаться его?

Foo *createFoo(const FooSpec *spec) { /* ... */ }
Foo *createFoo(const FooSpec &spec) { return createFoo(&spec); }

Могут ли возникнуть проблемы, вызванные неожиданными проблемами?

4b9b3361

Ответ 1

Должен быть только один способ сделать определенную вещь. Это сделает код более понятным для своих пользователей. Поэтому вы должны выбрать только один, в зависимости от семантики:

  • Если a nullptr является значимым значением, которое должно быть передано в createFoo, тогда объявите функцию для принятия указателя.

  • Если a nullptr не следует передавать в createFoo, тогда объявите параметр ссылкой, чтобы заставить крик компилятора у людей, которые попытаются пройти в nullptr.

Теперь пользователи вашего кода пойдут "Ах, я могу передать нуль этой функции, круто!" или "Хорошо, эта функция требует, чтобы фактический объект работал правильно".

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

Или как WhozCraig поместите его,

Выберите подходящую модель и сообщите клиентам "это ваш интерфейс".

Ответ 2

Я могу придумать одну весьма полезную причину для этого.

Версия Foo* может проверять значение null, обрабатывать этот случай и если не использовать ссылочный случай.

Foo& не может проверить значение null.

Это позволяет вызывающим абонентам сказать: "Я знаю, что это не null, потому что я проверил", сохраняя ветвь внутри функции.

Однако это преимущество (сохранение ветки) бессмысленно, как только стоимость метода проходит очень низкое значение.

Ответ 3

Программная кодовая база не является статическим объектом, она развивает с потребностями тех, кто ее использует. Если запутанный интерфейс является "плохой практикой" (я бы сказал, что это глупо), база кода может оказаться в такой ситуации, когда она развивается из рефакторинга и улучшения кода.

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

Также существует возможность передачи указателей nullptr_t (или NULL для старых таймеров, подобных мне) с помощью указателей const. Я не уверен в этом, учитывая, что вы можете перегружать методы своими аргументами, но опять же в контексте изменяющегося API это имеет смысл.


† он живой!!!