2012-07-06 38 views
6

Chúng ta hãy xây dựng mã mà tôi vừa mới tìm thấy ở đâu đó trong dự án:Enum giá trị va chạm với tên enum

namespace Test 
{ 
    enum EName 
    { 
     CoolEnum, 
     NiceEnum 
    }; 

    enum CoolEnum 
    { 
     CoolVal1, 
     CoolVal2 
    }; 

    enum NiceEnum 
    { 
     NiceVal1, 
     NiceVal2 
    }; 
} 

Câu hỏi của tôi là lý do tại sao các trình biên dịch cho phép một cái gì đó như thế này. Hãy lấy mẫu mã tại đây:

Test::CoolEnum cEnum = Test::NiceVal1; // INVALID, as compiler refers to Test::CoolEnum value of Test::Ename enum 

Tại sao sự nhầm lẫn đó được cho phép? Tôi hiểu tại sao tôi phải thêm từ khóa enum, vì vậy trình biên dịch biết rõ ràng rằng tôi đang khai báo một biến của enum đã cho, không sử dụng giá trị của enum khác trong cùng một không gian tên. Tôi chỉ không hiểu tại sao ngay từ đầu nó thậm chí còn có thể tạo ra một công trình như vậy. lớp enum

+0

Tôi đoán đó là trình biên dịch được xác định bởi vì mã trên Ideone gây ra lỗi: http://ideone.com/4GDTF – tinman

+0

Đó là lý do tại sao tôi đã đặt gcc nhưng theo như tôi biết vc cũng cho phép xây dựng như vậy –

+0

@Kamil bạn có thể muốn để thay đổi tên của hằng số enum của NiceEnum, kể từ khi bạn sao chép-dán nó từ CoolEnum và họ xung đột. –

Trả lời

7

C++ 11 của là giải pháp cho việc này:

namespace Test 
{ 
    enum class EName 
    { 
     CoolEnum, 
     NiceEnum 
    }; 

    enum class CoolEnum 
    { 
     NiceVal1, 
     NiceVal2 
    }; 

    enum class NiceEnum 
    { 
     NiceVal1, 
     NiceVal2 
    }; 
} 

Sau đó, bạn có thể sử dụng thích hợp NiceVal1:

Test::CoolEnum cEnum = Test::CoolEnum::NiceVal1; 

enums Plain được kế thừa từ C, nơi không có khái niệm không gian tên là gì. Nếu các enums đơn giản giới thiệu một số loại không gian tên, thì mã C sử dụng enums sẽ không biên dịch chút nào. Đó là lý do tại sao các lớp enum được giới thiệu, để không phá vỡ tính tương thích ngược.

+1

Điều cần biết, nhưng đó không phải là câu trả lời cho câu hỏi đã cho. Tôi rất vui vì trong C++ 11 họ đã dọn dẹp mọi thứ, nhưng tôi tự hỏi tại sao ở vị trí đầu tiên nó có thể là –

+0

Tôi đã đặt cùng một cấu trúc bên ngoài vùng tên và nó vẫn hoàn toàn hợp lệ cho C++ –

+0

Tôi không t hiểu những gì bạn đang đề cập đến, bạn có thể mở rộng hoặc cung cấp một ví dụ? – mfontanini

1

Câu trả lời là vì tiêu chuẩn ra lệnh cho hành vi này. Xem 3.3.7/2:

Tên lớp (9.1) hoặc tên liệt kê (7.2) có thể được ẩn theo tên của đối tượng, hàm hoặc điều tra được khai báo trong cùng phạm vi. Nếu tên lớp hoặc điều tra và đối tượng, chức năng hoặc điều tra là được khai báo trong cùng một phạm vi (theo thứ tự bất kỳ) có cùng tên, tên lớp hoặc tên điều tra bị ẩn ở bất kỳ đâu đối tượng, chức năng hoặc tên điều tra viên có thể nhìn thấy.

Có lẽ điều này là để tạo điều kiện tương thích với cơ chế của C (trong đó điều tra viên không mở phạm vi mới) đã được thiết lập trong một thời gian dài.

Trong trường hợp của bạn, ít nhất với g ++ bạn có thể sử dụng typename để cho biết bạn muốn sử dụng loại thay vì điều tra viên (typename Test::CoolEnum cEnum = Test::NiceVal1;).

Nói chung, tuy nhiên, tôi muốn chia sẻ tất cả các liệt kê trong một không gian tên hoặc lớp riêng biệt để ngăn chặn hoàn toàn các xung đột này.

+1

"typename Test :: CoolEnum" là không đúng - GCC xảy ra để chấp nhận rằng [nhưng nên từ chối nó] (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48920). Sử dụng "enum Test :: CoolEnum" để thay thế. –