23

Here is a C++ class that gets constructed with three values.

class Foo{

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

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

All of the parameter types are different.
I could overload the constructor so that order doesn't matter.

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;
};

But is that a good idea?
I started doing it because I knew what things a class/function needed;
I didn't always remember what order it took them in.


I've been assuming that the compiler optimizes this as if I called the same constructor.

//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");

What are your opinions on overloading a function so that the order doesn't matter?


Also, If I'm writing some utility functions,
Is it a good idea to provide different function names that do the same thing?

eg.

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

I don't often see these two but similar conventions.
Should I break or embrace the habit?

Trevor Hickey
  • 993
  • 1
  • 9
  • 16
  • 2
    One should only expend effort providing for multiple ways of expressing something if each explicitly-provided way will in some cases be clearly and unambiguously superior to any of the others. That doesn't mean one should generally expend effort ensuring that something can only be written in one canonical form, but it doesn't make sense to put forth effort allowing something to be specified in some way that isn't the best. – supercat Jan 16 '13 at 21:16
  • Kind of a duplicate of [my question here](http://stackoverflow.com/questions/7072768/what-is-the-canonical-way-to-make-a-function-accept-any-permutation-of-its-argum) (I now agree that it's a bad idea). – leftaroundabout Jan 16 '13 at 23:02

2 Answers2

95

I could overload the constructor so that order [of the parameters] doesn't matter... But is that a good idea?

No.

Having different constructor overloads will have the opposite effect of what you are intending. The programmer coming after you expects different overloads to have different behavior, and will ask: "What sort of different behavior is being expressed by each of these overloads?

Most programmers expect the discipline of having method parameters in a predefined order, and tools like IntelliSense will tell them the expected order of the parameters as they enter them.


Having multiple function names that do the same thing is the same problem; programmers expect the variants to have different behavior. One function or method per behavior, please, and just adopt a consistent naming pattern.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • 14
    lots of up-votes. I will stop immediately. thank you. – Trevor Hickey Jan 16 '13 at 18:09
  • 8
    In addition, you can't name constructors differently to explain your purpose, readers have to infer it from the parameters. Overloading the constructor this way makes it much harder to understand. – Zachary Yates Jan 16 '13 at 18:15
  • 3
    "Having multiple function names that do the same thing..." - for a 'good' time, look at Ruby's classes [String](http://www.ruby-doc.org/core-1.9.3/String.html#method-i-to_s) [Hash](http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-has_key-3F) [Array](http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-inspect) [File](http://www.ruby-doc.org/core-1.9.3/File.html#method-c-exist-3F). –  Jan 16 '13 at 18:42
  • +1. You are dealing with developers/programmers. Microsoft idea of "user is monkey", does not work here. – Manoj R Jan 17 '13 at 07:00
  • 1
    @ZacharyYates Lack of "constructor names" can be worked around by exposing a static construction methods instead. This is a standard practice in Java, although not so much in C++. – Xion Jan 21 '13 at 06:17
  • @MichaelT `to_s`, `to_str` and `inspect` do actually have different semantics though, it just so happens that a subset of them are internally implemented as aliases for String and Array because they output the same thing for these classes. – Nemo157 Jan 23 '13 at 07:42
  • @Nemo157 to_s and to_string are two methods that do exactly the same thing with the same semantics. Why have two different names for them? Or in Hash, `has_key?` and `include?` and `key?` and `member?`... –  Jan 23 '13 at 14:32
  • @MichaelT See http://briancarper.net/blog/98/ or `to_s` vs `to_str`, it's not very well defined but they are intended to have different meanings. I do agree that Hash has too many ways of checking its keys though... – Nemo157 Jan 23 '13 at 22:40
  • @Nemo157 an interesting read - the first time I've seen the intended differences between the methods. –  Jan 23 '13 at 22:47
14

Sometimes supporting commutation among arguments is necessary. For instance:

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

We do not want multiplication of an int and double to compute something different if the operands are reversed. Nor do we want to force programmers to remember that when multiplying ints and doubles, the double goes on the left!

It doesn't matter that this is an operator because the same goes for:

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

It really depends on the kinds of function. Whereas most programmers probably want support for commutativity in arithmetic libraries, they don't necessarily want, say, an I/O library functions to support all possible argument orders.

The concern probably hinges around the expected nesting in which the function calls are going to be involved. The flexibility in the arithmetic operators allows us to change the overall structure of the syntax tree to clarify the overall expression: group together similar terms and such.

Kaz
  • 3,572
  • 1
  • 19
  • 30