Berikut adalah opsi untuk bitmasks jika Anda tidak benar-benar menggunakan nilai enum individu (mis. Anda tidak perlu mematikannya) ... dan jika Anda tidak khawatir tentang mempertahankan kompatibilitas biner yaitu: Anda tidak peduli di mana bit Anda tinggal ... yang mungkin Anda berada. Anda juga sebaiknya tidak terlalu peduli dengan pelingkupan dan kontrol akses. Hmmm, enum memiliki beberapa properti bagus untuk bidang-bit ... ingin tahu apakah ada yang pernah mencobanya :)
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 :(";
}
}
Kita dapat melihat bahwa hidup ini hebat, kita memiliki nilai-nilai tersendiri, dan kita memiliki int bagus untuk & dan | untuk isi hati kita, yang masih memiliki konteks apa artinya bit. Semuanya konsisten dan dapat diprediksi ... bagi saya ... selama saya tetap menggunakan kompiler VC ++ Microsoft dengan Pembaruan 3 pada Win10 x64 dan jangan menyentuh bendera kompiler saya :)
Meskipun semuanya hebat ... kami memiliki beberapa konteks mengenai arti bendera sekarang, karena ini bersatu dengan bitfield di dunia nyata yang mengerikan di mana program Anda mungkin bertanggung jawab atas lebih dari satu tugas terpisah yang dapat Anda lakukan masih secara tidak sengaja (cukup mudah) menghancurkan dua bidang bendera dari serikat yang berbeda bersama-sama (katakanlah, AnimalProperties dan ObjectProperties, karena keduanya int), mencampur semua bit milik Anda, yang merupakan bug mengerikan untuk dilacak ... dan bagaimana saya tahu banyak orang di pos ini tidak terlalu sering menggunakan bitmask, karena membangunnya mudah dan mempertahankannya sulit.
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 :(
}
Jadi, Anda menjadikan deklarasi serikat pribadi untuk mencegah akses langsung ke "Bendera", dan harus menambahkan getter / setter dan kelebihan operator, lalu buat makro untuk semua itu, dan Anda pada dasarnya segera kembali ke tempat Anda memulai ketika Anda mencoba lakukan ini dengan Enum.
Sayangnya jika Anda ingin kode Anda portabel, saya tidak berpikir ada cara untuk A) menjamin tata letak bit atau B) menentukan tata letak bit pada waktu kompilasi (sehingga Anda dapat melacaknya dan setidaknya mengoreksi perubahan di seluruh versi / platform dll)
Diimbangi dalam struct dengan bidang bit
Saat runtime Anda dapat memainkan trik dengan mengatur bidang dan XOR bendera untuk melihat bit mana yang berubah, terdengar sangat jelek bagi saya meskipun ayat memiliki 100% konsisten, platform independen, dan solusi sepenuhnya deterministik yaitu: ENUM.
TL; DR: Jangan dengarkan para pembenci. C ++ bukan bahasa Inggris. Hanya karena definisi literal dari kata kunci yang disingkat yang diwarisi dari C mungkin tidak sesuai dengan penggunaan Anda, tidak berarti Anda tidak boleh menggunakannya ketika definisi C dan C ++ dari kata kunci tersebut benar-benar mencakup case use Anda. Anda juga dapat menggunakan struct untuk memodelkan hal-hal selain struktur, dan kelas untuk hal-hal selain sekolah dan kasta sosial. Anda bisa menggunakan float untuk nilai yang di-ground. Anda dapat menggunakan karakter untuk variabel yang tidak hangus atau orang dalam novel, drama, atau film. Setiap programmer yang masuk ke kamus untuk menentukan arti kata kunci sebelum spesifikasi bahasa adalah ... yah saya akan menahan lidah saya di sana.
Jika Anda ingin kode Anda dimodelkan setelah bahasa yang diucapkan Anda sebaiknya menulis di Objective-C, yang notabene juga menggunakan enum banyak untuk bitfield.
[Flags]
atribut berfungsi dengan baik yaitu:[Flags] enum class FlagBits{ Ready = 1, ReadMode = 2, WriteMode = 4, EOF = 8, Disabled = 16};