Является ли хорошей идеей предоставлять разные сигнатуры функций, которые делают одно и то же?

23

Вот класс C ++, который создается с тремя значениями.

class Foo{

    //Constructor
    Foo(std::string, int, char);

private:
    std::string foo;
    char bar;
    int baz;
};

Все типы параметров разные.
Я мог бы перегрузить конструктор, чтобы порядок не имел значения.

class Foo{

    //Constructors
    Foo(std::string, char, int);
    Foo(std::string, int, char);
    Foo(char, int, std::string);
    Foo(char, std::string, int);
    Foo(int, std::string, char);
    Foo(int, char, std::string);


private:
    std::string foo;
    char bar;
    int baz;
};

Но разве это хорошая идея?
Я начал это делать, потому что знал, что нужно классу / функции;
Я не всегда помнил, в каком порядке они их приняли.


Я предполагал, что компилятор оптимизирует это так, как если бы я вызывал один и тот же конструктор.

//compiler will implement this with the same code? 
//maybe not.. I could call a function to get a parameter, 
//and that function could change the state of the program, before calling
//a function to get another parameter and the compiler would have to
//implement both
Foo foo1("hello",1,'a');
Foo foo2('z',0,"world");

Что вы думаете о перегрузке функции, чтобы порядок не имел значения?


Кроме того, если я пишу некоторые служебные функции,
это хорошая идея, чтобы предоставить разные имена функций, которые делают то же самое?

например.

void Do_Foo();
void DoFoo();
void do_foo();
//etc..

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

Тревор Хикки
источник
1
Нужно только прилагать усилия для обеспечения нескольких способов выражения чего-либо, если каждый явно предоставленный способ в некоторых случаях будет явно и однозначно превосходить любой из других. Это не означает, что в общем случае нужно прилагать усилия для того, чтобы что-то можно было записать только в одной канонической форме, но не имеет смысла прилагать усилия, позволяющие что-то указать каким-то образом, что не является лучшим.
суперкат
Вроде дубликат моего вопроса здесь (теперь я согласен, что это плохая идея).
оставлено около

Ответы:

93

Я мог бы перегрузить конструктор, чтобы порядок [параметров] не имел значения ... Но разве это хорошая идея?

Нет.

Наличие различных перегрузок конструктора будет иметь противоположный эффект от того, что вы намереваетесь. Программист, следующий за вами, ожидает, что разные перегрузки будут иметь разное поведение, и спросит: «Какое разное поведение выражается каждой из этих перегрузок?

Большинство программистов ожидают дисциплины наличия параметров метода в предопределенном порядке, и такие инструменты, как IntelliSense, сообщат им ожидаемый порядок параметров при их вводе.


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

Роберт Харви
источник
14
много голосов за. Я немедленно остановлюсь. Спасибо.
Тревор Хики
8
Кроме того, вы не можете называть конструкторов по-разному, чтобы объяснить вашу цель, читатели должны вывести ее из параметров. Перегрузка конструктора таким образом усложняет понимание.
Захари Йейтс
3
«Наличие нескольких имен функций, которые делают одно и то же ...» - в «хорошее» время посмотрите на классы Ruby String Hash Array File .
+1. Вы имеете дело с разработчиками / программистами. Идея Microsoft «пользователь - обезьяна», здесь не работает.
Manoj R
1
@ZacharyYates Отсутствие «имен конструкторов» можно обойти, предоставив вместо этого статические методы конструирования. Это стандартная практика в Java, хотя не так много в C ++.
Сион
14

Иногда необходимо поддерживать коммутацию между аргументами. Например:

double operator *(int, double);
double operator *(double, int);

Мы не хотим умножать intи doubleвычислять что-то другое, если операнды обратные. Мы также не хотим заставлять программистов помнить, что при умножении ints и doubles, doubleслева идет!

Неважно, что это оператор, потому что то же самое относится к:

footype plus(const footype &, const bartype &);
footype plus(const bartype &, const footype &);

Это действительно зависит от видов функций. В то время как большинству программистов, вероятно, нужна поддержка коммутативности в арифметических библиотеках, они не обязательно хотят, скажем, библиотечные функции ввода / вывода для поддержки всех возможных порядков аргументов.

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

Kaz
источник