Một enum X : int
(C #) hoặc enum class X : int
(C ++ 11) là một loại có trường bên trong ẩn int
có thể chứa bất kỳ giá trị nào. Ngoài ra, một số hằng số được xác định trước X
được xác định trên enum. Có thể truyền enum đến giá trị nguyên của nó và ngược lại. Điều này hoàn toàn đúng trong cả C # và C ++ 11.
Trong C # enums không chỉ được sử dụng để giữ các giá trị riêng lẻ mà còn giữ các tổ hợp cờ theo bit, theo khuyến nghị của Microsoft . Các enum như vậy (thường, nhưng không nhất thiết) được trang trí với [Flags]
thuộc tính. Để làm cho cuộc sống của các nhà phát triển dễ dàng hơn, các toán tử bitwise (OR, AND, v.v ...) bị quá tải để bạn có thể dễ dàng làm một cái gì đó như thế này (C #):
void M(NumericType flags);
M(NumericType.Sign | NumericType.ZeroPadding);
Tôi là một nhà phát triển C # có kinh nghiệm, nhưng tôi chỉ lập trình C ++ được vài ngày và tôi không biết các quy ước C ++. Tôi dự định sử dụng enum C ++ 11 theo cách chính xác giống như tôi đã từng làm trong C #. Trong C ++ 11, các toán tử bitwise trên enum có phạm vi không bị quá tải, vì vậy tôi muốn quá tải chúng .
Điều này đã thu hút một cuộc tranh luận và ý kiến dường như khác nhau giữa ba lựa chọn:
Một biến của loại enum được sử dụng để giữ trường bit, tương tự như C #:
void M(NumericType flags); // With operator overloading: M(NumericType::Sign | NumericType::ZeroPadding); // Without operator overloading: M(static_cast<NumericType>(static_cast<int>(NumericType::Sign) | static_cast<int>(NumericType::ZeroPadding)));
Nhưng điều này sẽ chống lại triết lý enum được đánh máy mạnh mẽ của các enum có phạm vi của C ++ 11.
Sử dụng một số nguyên đơn giản nếu bạn muốn lưu trữ một tổ hợp enum bitwise:
void M(int flags); M(static_cast<int>(NumericType::Sign) | static_cast<int>(NumericType::ZeroPadding));
Nhưng điều này sẽ giảm tất cả mọi thứ thành một
int
, khiến bạn không có manh mối nào về loại mà bạn phải đưa vào phương thức.Viết một lớp riêng biệt sẽ quá tải toán tử và giữ các cờ bitwise trong trường số nguyên ẩn:
class NumericTypeFlags { unsigned flags_; public: NumericTypeFlags () : flags_(0) {} NumericTypeFlags (NumericType t) : flags_(static_cast<unsigned>(t)) {} //...define BITWISE test/set operations }; void M(NumericTypeFlags flags); M(NumericType::Sign | NumericType::ZeroPadding);
( mã đầy đủ của người dùng315052 )
Nhưng sau đó, bạn không có IntelliSense hoặc bất kỳ hỗ trợ nào để gợi ý cho bạn về các giá trị có thể.
Tôi biết đây là một câu hỏi chủ quan , nhưng: Tôi nên sử dụng phương pháp nào? Cách tiếp cận nào, nếu có, được công nhận rộng rãi nhất trong C ++? Cách tiếp cận nào bạn sử dụng khi xử lý các trường bit và tại sao ?
Tất nhiên vì cả ba phương pháp đều hoạt động, tôi đang tìm kiếm các lý do thực tế và kỹ thuật, các quy ước được chấp nhận chung, và không chỉ đơn giản là sở thích cá nhân.
Ví dụ, vì nền tảng C # của tôi, tôi có xu hướng đi theo cách tiếp cận 1 trong C ++. Điều này có thêm lợi ích là môi trường phát triển của tôi có thể gợi ý cho tôi về các giá trị có thể và với các toán tử enum quá tải, điều này dễ viết và dễ hiểu, và khá sạch sẽ. Và chữ ký phương thức cho thấy rõ loại giá trị mà nó mong đợi. Nhưng hầu hết mọi người ở đây không đồng ý với tôi, có lẽ vì lý do chính đáng.
enum E { A = 1, B = 2, C = 4, };
với phạm vi là 0..7
(3 bit). Do đó, tiêu chuẩn C ++ đảm bảo rõ ràng rằng # 1 sẽ luôn là một tùy chọn khả thi. [Cụ thể, enum class
mặc định enum class : int
trừ khi có quy định khác và do đó luôn có loại cơ bản cố định.])