Bir enum X : int
(C #) veya enum class X : int
(C ++ 11), int
herhangi bir değeri tutabilecek gizli bir iç alanına sahip olan bir türdür . Ek olarak, bir dizi önceden tanımlanmış sabit X
enumda tanımlanmıştır. Enum değerini tamsayı değerine çevirmek mümkündür; Tüm bunlar hem C # hem de C ++ 11 için geçerlidir.
C # enums değerleri yalnızca bireysel değerleri tutmak için değil, aynı zamanda Microsoft’un önerisine göre bitsel bayrak kombinasyonlarını tutmak için de kullanılır . Bu tür numaralandırmalar (genellikle, ancak zorunlu değil) [Flags]
özellik ile dekore edilir . Geliştiricilerin hayatlarını kolaylaştırmak için, bitsel operatörler (VEYA, VE, vb.) Aşırı yüklenir, böylece kolayca böyle bir şey yapabilirsiniz (C #):
void M(NumericType flags);
M(NumericType.Sign | NumericType.ZeroPadding);
Ben tecrübeli bir C # geliştiricisiyim, ancak birkaç gündür C ++ 'ı programladım ve C ++ sözleşmeleri ile bilmiyorum. C ++ 11 enum C # ile aynı şekilde kullanmak niyetindeyim. C ++ 11'de, geniş kapsamlı operatörlerdeki bitsel operatörler aşırı yüklenmez, bu yüzden onları aşırı yüklemek istedim .
Bu bir tartışma istedi ve görüşler üç seçenek arasında değişiyor gibi görünüyor:
Enum türünün bir değişkeni, bit alanını tutmak için kullanılır, C #'ya benzer:
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)));
Ancak bu, C ++ 11'in kapsamındaki enum'ların kuvvetle yazılmış enum felsefesine aykırı olacaktır.
Bitsel bir enums kombinasyonunu saklamak istiyorsanız düz bir tamsayı kullanın:
void M(int flags); M(static_cast<int>(NumericType::Sign) | static_cast<int>(NumericType::ZeroPadding));
Fakat bu, her şeyi azaltacaktır
int
, sizi metoda hangi türden koymanız gerektiğine dair hiçbir ipucu olmadan bırakacaktı.Operatörleri aşırı yükleyecek ve gizli bir tamsayı alanında bitsel bayrakları tutacak ayrı bir sınıf yazı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);
( user315052 tarafından tam kod )
Ancak daha sonra IntelliSense'e veya sizi olası değerlere işaret edecek herhangi bir desteğe sahip değilsiniz.
Bunun öznel bir soru olduğunu biliyorum ama: Hangi yaklaşımı kullanmalıyım? C ++ 'da en yaygın olarak bilinen yaklaşım hangisidir? Bit alanları ile uğraşırken hangi yaklaşımı kullanıyorsunuz ve neden ?
Elbette her üç yaklaşım da işe yaradığından beri, kişisel tercihlerden değil, genel ve kabul görmüş sözleşmelerden oluşan gerçek ve teknik sebepler arıyorum.
Örneğin, C # arkaplanım nedeniyle C ++ 'da yaklaşım 1' e gitme eğilimindeyim. Bu, geliştirme ortamımın beni muhtemel değerler konusunda ipuçlarına sokabileceğini ve aşırı yüklü enum operatörleriyle bunun yazılması ve anlaşılması kolay ve oldukça temiz olduğunu da ekledi. Ve yöntem imzası, ne tür bir değer beklediğini açıkça göstermektedir. Fakat buradaki çoğu insan muhtemelen iyi bir sebepten dolayı benimle aynı fikirde değil.
enum E { A = 1, B = 2, C = 4, };
aralık için 0..7
(3 bit) C ++ standardı açıkça # 1'in daima uygulanabilir bir seçenek olacağını garanti eder. [Özellikle, aksi belirtilmediği sürece enum class
varsayılan enum class : int
olarak belirlenir ve dolayısıyla her zaman sabit bir alt tipe sahiptir.])