Đây là một tùy chọn cho bitmasks nếu bạn không thực sự sử dụng cho các giá trị enum riêng lẻ (ví dụ: bạn không cần tắt chúng) ... và nếu bạn không lo lắng về việc duy trì khả năng tương thích nhị phân, tức là: bạn đừng quan tâm nơi bit của bạn sống ... mà bạn có thể là. Ngoài ra, bạn tốt hơn không nên quá quan tâm đến phạm vi và kiểm soát truy cập. Hmmm, enums có một số thuộc tính đẹp cho các trường bit ... tự hỏi liệu có ai đã từng thử nó chưa :)
struct AnimalProperties
{
bool HasClaws : 1;
bool CanFly : 1;
bool EatsFish : 1;
bool Endangered : 1;
};
union AnimalDescription
{
AnimalProperties Properties;
int Flags;
};
void TestUnionFlags()
{
AnimalDescription propertiesA;
propertiesA.Properties.CanFly = true;
AnimalDescription propertiesB = propertiesA;
propertiesB.Properties.EatsFish = true;
if( propertiesA.Flags == propertiesB.Flags )
{
cout << "Life is terrible :(";
}
else
{
cout << "Life is great!";
}
AnimalDescription propertiesC = propertiesA;
if( propertiesA.Flags == propertiesC.Flags )
{
cout << "Life is great!";
}
else
{
cout << "Life is terrible :(";
}
}
Chúng ta có thể thấy rằng cuộc sống thật tuyệt vời, chúng ta có những giá trị riêng biệt và chúng ta có một int đẹp và & | với nội dung trái tim của chúng tôi, vẫn có bối cảnh về ý nghĩa của các bit của nó. Mọi thứ đều nhất quán và có thể dự đoán được ... đối với tôi ... miễn là tôi tiếp tục sử dụng trình biên dịch VC ++ của Microsoft w / Cập nhật 3 trên Win10 x64 và không chạm vào cờ trình biên dịch của tôi :)
Mặc dù mọi thứ đều tuyệt vời ... hiện tại chúng tôi có một số bối cảnh về ý nghĩa của các lá cờ, vì nó nằm trong một liên minh với thế giới thực khủng khiếp nơi chương trình của bạn có thể chịu trách nhiệm cho nhiều hơn một nhiệm vụ riêng lẻ mà bạn có thể vẫn vô tình (khá dễ dàng) đập hai trường cờ của các hiệp hội khác nhau (giả sử AnimalProperives và ObjectProperies, vì cả hai đều là int), trộn lẫn tất cả các bit của bạn, đó là một lỗi khủng khiếp để truy tìm ... và làm sao tôi biết nhiều người trên bài đăng này không thường xuyên làm việc với bitmasks, vì việc xây dựng chúng rất dễ dàng và duy trì chúng là khó khăn.
class AnimalDefinition {
public:
static AnimalDefinition *GetAnimalDefinition( AnimalFlags flags ); //A little too obvious for my taste... NEXT!
static AnimalDefinition *GetAnimalDefinition( AnimalProperties properties ); //Oh I see how to use this! BORING, NEXT!
static AnimalDefinition *GetAnimalDefinition( int flags ); //hmm, wish I could see how to construct a valid "flags" int without CrossFingers+Ctrl+Shift+F("Animal*"). Maybe just hard-code 16 or something?
AnimalFlags animalFlags; //Well this is *way* too hard to break unintentionally, screw this!
int flags; //PERFECT! Nothing will ever go wrong here...
//wait, what values are used for this particular flags field? Is this AnimalFlags or ObjectFlags? Or is it RuntimePlatformFlags? Does it matter? Where's the documentation?
//Well luckily anyone in the code base and get confused and destroy the whole program! At least I don't need to static_cast anymore, phew!
private:
AnimalDescription m_description; //Oh I know what this is. All of the mystery and excitement of life has been stolen away :(
}
Vì vậy, sau đó bạn đặt tuyên bố liên minh của mình ở chế độ riêng tư để ngăn truy cập trực tiếp vào "Cờ" và phải thêm getters / setters và quá tải toán tử, sau đó tạo macro cho tất cả điều đó, và về cơ bản bạn đã quay lại ngay khi bạn cố gắng làm điều này với một Enum.
Thật không may nếu bạn muốn mã của mình có thể di động, tôi không nghĩ có bất kỳ cách nào để A) đảm bảo bố cục bit hoặc B) xác định bố cục bit tại thời điểm biên dịch (để bạn có thể theo dõi mã và ít nhất là chính xác cho các thay đổi trên phiên bản / nền tảng, v.v.)
Bù đắp trong một cấu trúc với các trường bit
Trong thời gian chạy, bạn có thể chơi các thủ thuật với các trường và XOR các cờ để xem bit nào đã thay đổi, nghe có vẻ khá nhảm nhí với tôi mặc dù các câu có giải pháp 100% nhất quán, độc lập với nền tảng và hoàn toàn xác định, ví dụ: ENUM.
TL; DR: Đừng nghe những người ghét. C ++ không phải là tiếng Anh. Chỉ vì định nghĩa theo nghĩa đen của từ khóa viết tắt được kế thừa từ C có thể không phù hợp với cách sử dụng của bạn không có nghĩa là bạn không nên sử dụng nó khi định nghĩa C và C ++ của từ khóa hoàn toàn bao gồm trường hợp sử dụng của bạn. Bạn cũng có thể sử dụng các cấu trúc để mô hình hóa những thứ khác ngoài cấu trúc và các lớp học cho những thứ khác ngoài trường học và đẳng cấp xã hội. Bạn có thể sử dụng float cho các giá trị được nối đất. Bạn có thể sử dụng char cho các biến không bị cháy cũng như một người trong tiểu thuyết, vở kịch hoặc phim. Bất kỳ lập trình viên nào đi vào từ điển để xác định ý nghĩa của từ khóa trước thông số ngôn ngữ là ... tôi sẽ giữ lời nói của mình ở đó.
Nếu bạn thực sự muốn mã của mình được mô hình hóa theo ngôn ngữ nói thì tốt nhất bạn nên viết bằng Objective-C, điều này cũng vô tình sử dụng enums rất nhiều cho bitfield.
[Flags]
thuộc tính chỉ hoạt động tốt, tức là:[Flags] enum class FlagBits{ Ready = 1, ReadMode = 2, WriteMode = 4, EOF = 8, Disabled = 16};