views:

144

answers:

8

In my header, I have a prototype declaration like this:

void move(int, int);

I can omit the parameter names, that's how I'm used to it from C. I do that so that I don't have to keep the parameter names in sync - it's extremely confusing if they differ between prototype and implementation.

Right now, I'm documenting all of my code with Doxygen, and I decided to put all comments into the header. Now I have to refer to parameter names that are defined in the implementation but not in the header: I find that confusing.

/**
 * Moves the entity to the specified point.
 * @param x The x coordinate of the new position.
 * @param y The y coordinate of the new position.
 */
void move(int, int);

In the generated Doxygen HTML, it is not easy to figure out which parameter is which. Of course, one could follow the same order here, but if one has many parameters, it is still confusing.

The alternative would be to duplicate parameter names and try to keep them in sync. However, some people don't encourage this approach, saying that header parameters should start with a double underscore so that the user of a method can not possibly use the same name (names starting with __ are disallowed in C++).

How do you do it?

A: 

C and C++ are the same in this regard. The prototype names don't need to match up… that's why they may be omitted.

Pick names for the parameters; when you put them in Doxygen they become part of your API. You can change them later, but you're changing the API; you can change them in the implementation as well but then it won't match the spec as cleanly.

Do not use a double underscore, even for "ignored" identifiers. The compiler may define anything beginning with double underscore to mean anything, potentially causing a syntax error. Such words aren't just forbidden for names of in-scope variables, they are completely toxic.

Potatoswatter
They don't have to match up, but they can't be omitted in C. C and C++ are _different_ in this regard.
Charles Bailey
@Charles, they can be omitted in C: "A parameter type list specifies the types of, and _may_ declare identifiers for, the parameters of the function" (c99, 6.7.5.3, my italics).
paxdiablo
My mistake, I remembered incorrecty. The difference is that in C the parameter names cannot be omitted in the function _definition_, which is different from C++. (Hence the more common use of an UNUSED macro for parameters in C.)
Charles Bailey
+2  A: 

They don't need to match, but I find parameter names to be invaluable documentation. I hate it when they're missing. I like in-code documentation far better than documentation in comments.

And the advice at the end of that link is really silly. Parameter names are nothing special as far as being in danger of being redefined by a #define. Function names and practically any other identifier in your header are in danger as well. That's why the naming convention of using ALL_UPPERCASE for your #define names exists.

No, make the names match in your implementation and in your header, even though the compiler will be fine if they don't. And if they don't match, fix it so they do. They provide excellent documentation and they will be confusing if they don't match.

Omnifarious
+1 - I tend to be descriptive in my header file, e.g. move(int xcoord, int ycoord); but then in my definition I might just use x, y. move could be row/column-based, which is backwards from x/y coordinate, e.g. move(int row, int column); so then move(int, int); for some clients may be interpreted incorrectly WITHOUT the documentation or the named parameters.
franji1
+4  A: 

Surely if "names starting with __ are disallowed in C++", you shouldn't be using them in prototypes either :-) *a

I see two ways to do it.

One, you can ensure that the order of parameters in your comments always matches the order in your prototype.

Or, two, you could actually put the real names in your prototypes as well.

Myself, I prefer the second approach since I like to be able to tell what parameters are passed in, even if the function has no comments on it (or worse, the comments get out of date). This is far easier with a prototype like:

void move(int xcoord, int ycoord);

than it is with:

void move(int, int);

In some environments, we've even gone so far as to have the build process ensure that all function prototypes have identically named parameters as the function definition.


*a) These identifiers are actually not for the use of regular programs. Section 17.6.3.3.2 of cpp0x (but this restriction has been around for quite a while in both C and C++) states:

Certain sets of names and function signatures are always reserved to the implementation:

  • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
  • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.

In other words, don't use them for your own purposes.

paxdiablo
+4  A: 

It is a terrible idea to not name the parameters in the header if it is not clear what that parameter is for. The header should be the documentation for your code, so that someone trying to use it can avoid reading the implementation. As you found, it's pointless to document the parameters by name and then not tell the user which is which. That's not to say that they must match, but in the header they should be meaningful for the users of your code. In the implementation, choose the name that is best for you. E.g. it would be totally feasible to have:

.h:

void move(int x, int y);

.cpp:

void move(int deltaX, int deltaY)
{
   ...

The only times that it would make sense (if you care about other programmers using your code) to elide the parameter names is when it is bone crushingly obvious what that parameter does. E.g.

void SetNumPotatoes(int);
void EnableLights(bool);
void InitFoo(Foo&);

// but then...
T& GetItem(int);  // probably obvious enough, but does typing 'index' kill you?
void DoSomething(bool, float, int);  // someone using this will say, "WTF?"
dash-tom-bang
+1 just for `void SetNumPotatoes(int);`
Praetorian
A: 

I always use parameter names both in header and in implementation. It is not difficult to keep them in sync - when I change the function parameters, I usually:
* Add/remove a parameter (no problem here - you have to sync it even if you didn't use parameter names)
* Change the order to be more logical (again, even the types have to be synced)

The advantage of having the parameter names in both prototype and implementation is that it helps the user - he can see the names in his IDE code completion, he doesn't have to navigate to the definition (which might be unavailable) to find out the parameter names. Another good reason for sticking to this practice is your Doxygen problem.

I also don't really see the point of using double underscores in prototype parameters. Yes, #defines are evil, but double underscores are reserved for compiler writers. Unless you write a standard header for your compiler, you should avoid it.

dark_charlie
+1  A: 

WRONG documentation/parameter names is ALWAYS WORSE than NO documentation/parameter names. I'm not saying you don't need documentation or parameter names - I'm saying that you better keep up with them! That's why they pay us the big $$$ :-D

franji1
+1 for the WRONG documentation related input
Chubsdad
A: 

If the header file belongs to an OEM library which is expected to be used by many third party vendors, inquisitive developers (such as those belonging to SO), will most certainly explore the header files in addition to the supplied documentation, given the fact that most of the time documentation is either very bad or lags significantly behind the code.

Therefore, I would say, the issues cited about the naming the parameters could be a development time pain, but is almost certainly a customer's delight.

Chubsdad
A: 

Hi,

What is protype declaration is that you are informing compiler that this type of function is going to come with this arguments and with this data types. So compiler will make arrangemnts for that type of arguments.

hence proto data type and number of arguments should match with the actual definition and run time usage.

Otherwise it will give an run time error.

ksrao