2010-08-22 42 views
7

在我的头,我有一个原型声明是这样的:原型参数名称

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++中不允许以__开头的名称)。

你怎么做到的?

+3

你提到的“鼓励”一个前导双下划线的帖子完全没有这种功能。海报是说这种行为是编译器和标准库的作者所保留的。即“除你以外的人”。 :) – 2010-08-22 09:12:54

+0

啊,好的。你们在这个问题上似乎都有相同的看法,所以我认为这是回答:)我很乐意将所有答案都标记为“接受”。 – halifar 2010-08-22 09:39:26

回答

5

当然,如果“开始__名在C++中是不允许的”,你不应该在原型要么:-) *一个

我看到两种方法可以做到这一点使用它们。

一,您可以确保您的评论中的参数顺序始终匹配原型中的顺序。

或者,您可以将真实姓名放在您的原型中。

我自己,我更喜欢第二种方法,因为我喜欢能够告诉哪些参数被传入,即使该函数没有评论(或者更糟糕的是,评论过期)。这是更容易与原型一样:

void move(int xcoord, int ycoord); 

比是:

void move(int, int); 

在某些环境中,我们甚至走得更远,它们甚至有构建过程确保所有的函数原型与函数定义具有相同的命名参数。


*一)这些标识符实际上不是使用常规的程序。第cpp0x的17.6.3.3.2(但这个限制已经出现在C和C++相当长的一段)指出:

名称和功能特征的一组特定总是保留给实现:

  • 每个包含双下划线的名称__或以下划线开头且后面带有大写字母的字符将保留给实施用于任何用途。
  • 以下划线开头的每个名称都保留给实现,以用作全局名称空间中的名称。

换句话说,不使用它们自己的目的。

0

C和C++在这方面是一样的。原型名称不需要匹配...这是为什么它们可能会被省略。

选择参数的名称;当你把它们放在Doxygen中时,它们就成为你API的一部分。您可以稍后更改它们,但您正在更改API;你也可以在实现中改变它们,但是它不会完全符合规范。

即使对于“被忽略的”标识符,也不要使用双下划线。编译器可以定义任何以双下划线开头的含义来表示任何内容,这可能会导致语法错误。这些词不仅限于范围内变量的名称,它们完全是有毒的。

+0

它们不必匹配,但它们不能在C中省略。在这方面,C和C++是_different_。 – 2010-08-22 09:33:01

+0

@Charles,它们可以在C中省略:“参数类型列表指定函数的参数的类型,并且_may_声明标识符的参数”(c99,6.7.5.3,my italics)。 – paxdiablo 2010-08-22 09:47:24

+0

我的错误,我记得不正确。不同的是,在C中,参数名称不能在_definition_中省略,该函数与C++不同。 (因此,对于C中的参数,更常见的是使用UNUSED宏。) – 2010-08-22 10:10:04

3

他们不需要匹配,但我发现参数名称是无价的文档。当他们失踪时,我讨厌它。我喜欢代码文档比评论中的文档更好。

并且该链接末尾的建议非常愚蠢。只要有被#define重新定义的危险,参数名就没什么特别之处。头部中的函数名称和几乎任何其他标识符都处于危险之中。这就是为什么使用ALL_UPPERCASE命名约定存在#define名称的原因。

不,在你的实现和你的头文件中使名称匹配,即使编译器没有的话也可以。如果它们不匹配,请修复它,以便它们能够做到。它们提供了出色的文档,如果它们不匹配,它们会很混乱。

+0

+1 - 我倾向于在我的头文件中描述,例如move(int xcoord,int ycoord);但是在我的定义中,我可能只是使用x,y。移动可以是基于行/列的,这是从x/y坐标向后,例如,移动(int row,int column);然后移动(int,int);对于某些客户端可能会被错误地解释而没有文档或命名参数。 – franji1 2010-08-22 19:46:42

10

这是一个可怕的想法,如果不清楚该参数是用于标题中的参数。头文件应该是你的代码的文档,所以有人试图使用它可以避免阅读实现。如你所见,通过名称记录参数是毫无意义的,然后不告诉用户哪个是哪个。这并不是说它们必须匹配,但是在标题中它们应该对代码的用户有意义。在实施过程中,选择最适合您的名称。例如。这将是完全可行的有:

.H:

void move(int x, int y); 

的.cpp:

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

唯一的时间,它才有意义(如果你使用你的代码关心其他的程序员)来消除参数名称的时候,它是骨头破坏性明显的参数。例如。

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?" 
+2

+1仅用于'void SetNumPotatoes(int);' – Praetorian 2010-08-23 03:07:32

1

我始终在头文件和实现中都使用参数名称。使它们保持同步并不困难 - 当我更改功能参数时,我通常会:
*添加/删除参数(这里没有问题 - 即使您没有使用参数名称也必须同步)
*(再次,连类型都必须同步)更改为更符合逻辑

有两个原型和执行参数名的好处是,它可以帮助用户 - 他可以看到名字他的IDE代码完成后,他不必导航到定义(可能不可用)以查找参数名称。坚持这种做法的另一个好的理由是你的Doxygen问题。

我也没有真正看到在原型参数中使用双下划线的要点。是的,#定义是邪恶的,但是双下划线是为编译器编写者保留的。除非您为编译器编写标准头文件,否则应该避免使用它。

2

WRONG文档/参数名称总是比NO文档/参数名称更糟糕。我并不是说你不需要文档或参数名称 - 我说你最好跟上他们!这就是为什么他们付给我们大的$$$:-D

+1

+1用于WRONG文档相关输入 – Chubsdad 2010-08-23 02:52:23

0

如果头文件属于许多第三方供应商希望使用的OEM库,那么好奇的开发人员(例如属于SO的开发人员)将除了提供的文档之外,肯定会探索头文件,因为大部分时间文档都非常糟糕,或者远远落后于代码。

因此,我想说,关于命名参数的问题可能是是一个开发时间的痛苦,但几乎肯定是客户的喜悦。

0

什么是protype声明是你告诉编译器这种类型的函数将带有这个参数和这个数据类型。所以编译器会为这种类型的参数进行排列。

因此,原型数据类型和参数个数应该与实际的定义和运行时使用率匹配。

否则它会给运行时间错误。