在我的标题中,我有一个这样的原型声明:
void move(int, int);
我可以省略参数名称,这就是我从C中习惯的方法。我这样做是为了让我不必保持参数名称同步 - 如果它们在原型和实现之间有所不同,那就非常混乱了。
现在,我正在使用Doxygen记录我的所有代码,并且我决定将所有注释放入标题中。现在我必须引用在实现中定义但不在头文件中定义的参数名称:我发现这令人困惑。
/**
* 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);
在生成的Doxygen HTML中,要弄清楚哪个参数是哪个参数并不容易。当然,这里可以遵循相同的顺序,但如果有一个参数很多,那么它仍然令人困惑。
替代方法是复制参数名称并尝试使它们保持同步。但是,some people不鼓励这种方法,说标题参数应该以双下划线开头,以便方法的用户不可能使用相同的名称(在_C ++中不允许以__开头的名称)。 / p>
你是怎么做到的?
答案 0 :(得分:10)
如果不清楚该参数的用途,那么在标题中不命名参数是一个可怕的想法。标题应该是代码的文档,以便尝试使用它的人可以避免阅读实现。正如您所发现的那样,按名称记录参数是没有意义的,然后不告诉用户哪个是哪个。这并不是说它们必须匹配,但在标题中它们应该对代码的用户有意义。在实施中,选择最适合您的名称。例如。拥有:
是完全可行的·H:
void move(int x, int y);
的.cpp:
void move(int deltaX, int deltaY)
{
...
唯一有意义的事情(如果你关心使用你的代码的其他程序员)来消除参数名称的唯一时刻就是它很明显地表明了该参数的作用。 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?"
答案 1 :(得分:5)
当然,如果“在C ++中不允许以__开头的名字”,你不应该在原型中使用它们:-) * a
我认为有两种方法可以做到。
其一,您可以确保评论中参数的顺序始终与原型中的顺序相匹配。
或者,两个,您实际上也可以将真实姓名放在原型中。
我自己,我更喜欢第二种方法,因为我希望能够告诉传入哪些参数,即使函数没有注释(或者更糟糕的是,注释已经过时)。使用像
这样的原型,这要容易得多void move(int xcoord, int ycoord);
比以下:
void move(int, int);
在某些环境中,我们甚至已经让构建过程确保所有函数原型都具有与函数定义相同的参数。
* a)这些标识符实际上不适用于常规程序。 cpp0x的第17.6.3.3.2节(但这种限制在C和C ++中已存在很长时间)状态:
某些名称和功能签名集始终保留给实现:
- 包含双下划线
__
或以下划线后跟大写字母开头的每个名称都保留给实现以供任何使用。- 以下划线开头的每个名称都保留给实现,以用作全局命名空间中的名称。
换句话说,不要将它们用于您自己的目的。
答案 2 :(得分:3)
它们不需要匹配,但我发现参数名称是无价的文档。当他们失踪时,我讨厌它。我喜欢代码文档比评论中的文档好得多。
该链接结尾处的建议真的很愚蠢。参数名称没有什么特别之处,只要有被#define
重新定义的危险。标题中的函数名称和几乎任何其他标识符也存在危险。这就是为什么存在使用ALL_UPPERCASE作为#define
名称的命名约定。
不,在您的实现和标题中使名称匹配,即使编译器没有,也可以。如果它们不匹配,请将其修复。它们提供了出色的文档,如果它们不匹配,它们会让人感到困惑。
答案 3 :(得分:2)
错误的文档/参数名称总是比NO文档/参数名称更糟糕。我不是说你不需要文档或参数名称 - 我说你最好跟上它们!这就是为什么他们向我们支付了大笔费用:-D
答案 4 :(得分:1)
我总是在标头和实现中使用参数名称。让它们保持同步并不困难 - 当我改变功能参数时,我通常会:
*添加/删除参数(此处没有问题 - 即使您没有使用参数名称也必须同步它)
*更改顺序更合乎逻辑(同样,甚至必须同步类型)
在原型和实现中使用参数名称的优点是它可以帮助用户 - 他可以在IDE代码完成中看到名称,他不必导航到定义(可能不可用)到找出参数名称。坚持这种做法的另一个好理由是你的Doxygen问题。
我也没有真正看到在原型参数中使用双下划线的意义。是的,#define是邪恶的,但是双重下划线是为编译器编写者保留的。除非为编译器编写标准头文件,否则应该避免使用它。
答案 5 :(得分:0)
选择参数名称;当你把它们放入Doxygen时,它们就成了你的API的一部分。您可以稍后更改它们,但是您正在更改API;您也可以在实现中更改它们,但它不会完全符合规范。
不要使用双下划线,即使是“忽略”标识符也是如此。编译器可以定义以双下划线开头的任何内容来表示任何内容,可能导致语法错误。这些词不仅仅被禁止用于范围内变量的名称,它们完全有毒。
答案 6 :(得分:0)
如果头文件属于预期由许多第三方供应商使用的OEM库,好奇的开发人员(例如那些属于SO的开发人员)除了提供的文档之外,肯定会探索头文件。事实上,大部分时间文档要么非常糟糕,要么落后于代码。
因此,我想说,引用命名参数的问题可能是一个开发时间的痛苦,但几乎可以肯定是客户的喜悦。
答案 7 :(得分:0)
什么是protype声明是你通知编译器这种类型的函数将带有这个参数和这些数据类型。所以编译器会为这种类型的参数做出安排。
因此,proto数据类型和参数数量应与实际定义和运行时使用相匹配。
否则会产生运行时错误。