2011-05-23 85 views
5

這個問題需要一些探索,對不起。我在解析一些C++代碼的doxygen中修正了一個疏忽,並且遇到了doxygen沒有考慮到的不尋常的角落案例。我有一個修復,但我想使它更通用,所以我需要一些解釋。C++對於哪些類型,參數類型名稱可以與具有類型說明符的參數名稱相同?

爲了說明doxygen失敗的情況,我將定義一個涉及辛普森一家人爲的例子(因爲這似乎是這些類型的問題很受歡迎)。比方說,我們有以下枚舉:

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

現在我們要枚舉值傳遞到(辛普森類自然的)的方法,看起來像這樣:

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」視爲一個參數類型,沒有參數名稱。在上面的enum的情況下,我想出了一些代碼來修復doxygen。

我的問題是,這種技巧有效的其他類型? struct?,union?,typedef?,其他?對於這個問題,「方法參數的類型說明符與參數名稱相同」的概念有一個名稱,以便我可以獲得更多的細節。

+0

不錯(呃......在「我不知道」這個意思,但不是_nice_)的伎倆。 – 2011-05-23 02:22:46

+1

請原諒我,而我發現誰寫了這些代碼,並將他們在臉上:P。 – 2011-05-23 02:45:14

+0

什麼編譯器和版本?上面的代碼示例應該編譯時不需要*詳細的類型說明符*。 – 2011-05-23 07:44:38

回答

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中執行,其中總是需要詳細的類型說明符。只有這樣也會失敗,編譯器纔會移動到下一個作用域。

+0

gcc 2.95.3。最後測試了這一點,你是正確的,枚舉部分不需要C++代碼中的方法參數,但需要聲明該類型的局部變量。我沒有檢查枚舉是否需要用於常規函數的參數,因爲我沒有使用它們。 – 2013-07-08 23:24:47

1

struct/class/union也。在標準中,「精確類型說明符」由「類別標識符」組成,見3.4.4-1。 (順便說一句 - 如果switchcasereturn S,它沒有必要break

+0

我知道我會將示例代碼中的東西搞砸,因爲我沒有編譯它。 – 2011-05-23 02:41:35

+0

@John::-)。即使這樣也不會發現它 - 就像編譯和工作得很好......只是那些在執行過程中永遠無法達到的「break」行 - 無論如何都應該被優化器刪除,但代碼在沒有的情況下會更好地讀取。 – 2011-05-23 02:51:10

3

在C,一個structunion的規範名稱,或enum包括前綴:

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++有這個問題,以及,具有相同的行爲調查分析r也給予class,以及在模板中給予templatetypename的類似行爲。但是,除了在不明確的情況下,它也消除了包括前綴的要求。

我不認爲這個概念有一個名字,但我糾正:這是一個闡述類型說明符。一個適當的解決方法可能是將Doxygen註釋放在聲明中而不是定義上。

+0

你的回答很好。託尼只有在知道這被稱爲「詳細說明類型說明符」的情況下才得到了接受的答案。 – 2011-05-23 02:52:46

1

你在那裏做的事情與C編程人員整天都在做的事情相同 - 用適當的關鍵字爲用戶定義的類型加上前綴。基本上,對於struct,class,union,typedefs,變量聲明,基本上都是一樣的。

相關問題