C ++什么类型的参数类型名称可以与带有类型说明符的参数名称相同?

时间:2011-05-23 02:17:21

标签: c++ parameters enums specifier

这个问题需要一些探索,对不起。我正在修复doxygen解析一些C ++代码的疏忽,我遇到了一个不寻常的角落情况,doxygen没有考虑到。我有一个修复,但我想让它更通用,所以我需要一些解释。

为了说明doxygen失败的情况,我将定义一个涉及“辛普森一家”的人为例子(因为这似乎在这些类型的问题中很受欢迎)。假设我们有以下枚举:

enum simpson { HOMER, MARGE, BART, LISA, MAGGIE };

现在我们要将枚举值传递给一个方法(自然是Simpsons类),如下所示:

const char* voicedBy(simpson simpson)
{
    switch (simpson) {
        case HOMER:
            return "Dan Castellaneta";
        case MARGE:
            return "Julie Kavner";
        case BART:
            return "Nancy Cartwright";
        case LISA:
            return "Yeardley Smith";
        case MAGGIE:
            return "*suck* *suck*";
    }
}

不幸的是,这会产生编译器错误,因为不允许枚举类型'simpson'与参数名称'simpson'相同(与C#不同)。但是,C ++有一个答案。您将enum关键字放在类型名称前面,如下所示:

const char* voicedBy(enum simpson simpson)

现在代码将编译并运行。不幸的是,doxygen没有考虑到这种情况,所以它将整个字符串“enum simpson simpson”视为没有参数名称的参数类型。我已经提出了一些代码来修复doxygen,就像上面的枚举一样。

我的问题是,这种技巧有哪些其他类型? struct?,union?,typedef?,其他?就此而言,与参数名称'概念同名的方法参数的'类型说明符'是否有一个名称,以便我可以获得更多详细信息?

4 个答案:

答案 0 :(得分:3)

在C中,structunionenum的规范名称包含该前缀:

struct Point {
    int x, y;
};

enum Type {
    FIRST, SECOND, THIRD
};

struct Point p;
enum Type t;

创建带有前缀的typedef名称的成语的来源是哪一个:

typedef struct Point {
    int x, y;
} Point;

typedef enum Type {
    FIRST, SECOND, THIRD
} Type;

struct Point p;
enum Type t;
Point p;
Type t;

C ++也有这一点,同样的行为也赋予了class,以及模板中templatetypename的类似行为。但是,除了不明确的情况外,它还删除了包含前缀的要求。

我不认为这个概念有一个名字,但我有所纠正:它是一个精心设计的类型说明符。对此的合适解决方法可能是将Doxygen注释放在声明而不是定义上。

答案 1 :(得分:2)

您使用的是什么编译器和版本?

void foo( simpson simpson ) {}

没有enum存在,也就是说,您不需要在此上下文中使用详细的类型说明符,并且它在gcc 4.2和4.6中完美编译。问题是里面函数,参数名称隐藏了 * 类型,如果你想在中声明一个带有类型的新变量那个范围你需要精心设计的类型说明符,但在函数签名中它从左到右解析,这意味着第一个simpson是枚举,那时没有碰撞。第二个simpson引入了一个本地名称,从那里开始,simpson引用参数而不是类型。

void relationship( /*enum*/ simpson simpson, enum simpson other = HOMER );
//                   ^^^^ optional           ^^^^ required
{
   enum simpson yet_another = simpson;
// ^^^^ required              ^^^^^^^ first argument!
}

如果定义一个与所需类型同名的函数,则会发生相同类型的名称​​隐藏

void simpson();
void voicedBy( enum simpson s );
//             ^^^^ required

请注意,如果添加一个typedef,在最后一种情况下会发生一些变化:typedef-ed名称和函数名称之间会有名称冲突(或同一范围内的变量名称)。

* 这里隐藏不是在一个范围内的变量意义上使用,隐藏外部范围内具有相同名称的变量。在C ++中,与C一样,有两个标识符空间,一个用于用户定义的类型,另一个用于其他所有其他标识符空间,包括typedef - ed类型别名。在C ++中查找从内部作用域到外部作用域,并且在每个作用域中搜索全局标识符空间,如果未找到标识符,则在用户定义的类型标识符空间中搜索相同的标识符。最后一步不是在C中执行的,其中始终需要精心设计的类型说明符。只有当它也失败时,编译器才会移动到下一个范围。

答案 2 :(得分:1)

struct / class / union也是。在标准中,“详细类型说明符”由“类密钥标识符”组成,见3.4.4-1。 (顺便说一句 - 如果是switch case return,则无需break。)

答案 3 :(得分:1)

你所做的是C编码员整天做的事情 - 用他们的用户定义的类型加上适当的关键字。结构,类,联合,typedef,变量声明,基本上都适用。