2010-02-12 58 views
10

我有一個類和枚舉值具有相同的名稱。在課堂內部,我想使用提供錯誤的枚舉。有沒有辦法使用枚舉而不用重命名或移動到不同的命名空間?使用類和枚舉相同的名稱?

例子:

namespace foo { 
    enum bar { 
     BAD 
    }; 

    class BAD { 
     void worse() { 
      bar b = BAD; // error 
     } 
    }; 
}; 
+0

哦,請......不能把枚舉放在自己的'struct'中以避免衝突,至少? – 2010-02-12 11:46:08

+0

爲了提高可讀性,我強烈建議爲'enum'和'class'選擇不同的名稱。請記住,一個更好的目標是產生易於維護的軟件,而不是在編譯器或語言中調用微妙的東西。 – 2010-02-12 17:50:43

回答

9

這是如何執行名稱查找的棘手部分之一。

C++中有兩個標識符作用域,一個用於類類型和一般標識符作用域。枚舉值BAD駐留在通用標識符範圍中,而類類型BAR駐留在類標識符範圍中。這就是爲什麼您可以同時使用枚舉值和類名的原因:兩個名稱不會發生衝突。

在類BAD中,標識符查找規則將在找到枚舉之前查找類BAD,從而發現錯誤。現在,如果您完全限定標識符,那麼名稱查找將首先檢查全局標識符範圍並匹配枚舉值。在另一端,您將不得不添加structclass關鍵字來聲明BAD類型的變量。

namespace foo { 
    enum bad { BAD; }; 
    class BAD { 
     void worse() { bad b = ::foo::BAD; } // fully qualified will match the enum 
    }; 
} 
int main() { 
    // foo::BAD b; // error, foo::BAD is an enum, not a type 
    class foo::BAD b; // correct 
} 

現在,我會反對這種用法。重用這樣的標識符通常不是一個好主意。代碼會更復雜,並且可能會讓讀者產生誤解(同一個非限定標識符在不同環境中使用時指的是不同的東西)。如果名稱必須是BAD,請考慮爲類或枚舉使用封閉的名稱空間或類(更喜歡那裏的枚舉)。

0

沒有,有沒有辦法做到這一點。你應該使用有效的標識符。有效的標識符意味着您必須能夠識別。 :)

5
bar b = foo::BAD; 

,或者如果你是在全局命名空間

bar b = ::BAD; 

但這名超載是不是我推薦。 C++ 0X將允許

bar b = bar::BAD; 

這是一個更好的解決方案,如果依賴於C++ 0X是可以接受的。

作爲承諾,說明

9.1/2

如果一個類名稱被在一個範圍中聲明,其中一個對象,功能,或具有相同名稱的枚舉還聲明,那麼雙方的聲明在範圍內,類可以被稱爲僅使用闡述型說明符(3.4.4)

闡述型說明符是形式

class BAD b; 

這對於具有C兼容性,其中標籤名稱是在一個不同的名稱空間,並且必須是[I]的typedef [/ I] ED如果一個要使用它們沒有詳細闡述,類型 - 符。 (一個衆所周知的函數示例是Unix中的struct stat和函數stat)。

這解釋了爲什麼重載名稱來指定類和枚舉器是可能的。 BAD指定類的原因在於類的名稱也被定義爲類作用域,並且在成員函數定義中搜索的作用域依次爲: - 成員函數作用域 - 類作用域 - 包含類定義的名稱空間

在類作用域中發現BAD,因此從不搜索名稱空間foo。

+0

有人想知道我是否嘗試過。我使用了3種不同的編譯器,包括como。這些規則是神祕的,如果我記得有時間的話,我會用參考文獻給出更全面的解釋。 – AProgrammer 2010-02-12 10:02:21

+0

++,你對此正確 – 2010-02-12 14:39:56

0

這個工程在VS2008,但給出了一個警告:

bar b = bar::BAD; 

它不是我可以推薦。

您應該將枚舉放入foo之內的另一個名稱空間中,並將barBAD與新命名空間相匹配。

+0

這是C++ 0X語法,如果可用,它是首選解決方案。我的解決方案是C++ 03語法(但使用奧術規則)。 – AProgrammer 2010-02-12 10:03:46