Typ wyliczenia CLR
Deklaracja i zachowanie tekstów stałych zmienił się z rozszerzenia zarządzane dla języka C++ do Visual C++.
Deklaracja typu wyliczeniowego rozszerzeń zarządzanych jest poprzedzony __value słowa kluczowego.Idea jest odróżnienia macierzystego enum enum CLR, który pochodzi od System::ValueType, zgłaszając analogicznych funkcji.Na przykład:
__value enum e1 { fail, pass };
public __value enum e2 : unsigned short {
not_ok = 1024,
maybe, ok = 2048
};
Nowe elementy składni rozwiązuje problem rozróżniania macierzystego i teksty stałe CLR przez podkreślając istotę klasy te ostatnie raczej niż jego wartość typu korzenie.Jako takie __value słowo kluczowe jest odrzucany, zastąpione parę słowo kluczowe rozmieszczone enum class.Zapewnia to Symetria pary słowo kluczowe deklaracje odniesienia, wartości i klasy interfejsu:
enum class ec;
value class vc;
ref class rc;
interface class ic;
Tłumaczenie pary wyliczenie e1 i e2 w nowe elementy składni wygląda następująco:
enum class e1 { fail, pass };
public enum class e2 : unsigned short {
not_ok = 1024,
maybe, ok = 2048
};
Z wyjątkiem małych zmian porowata z zachowaniem CLR typu enum został zmieniony na wiele sposobów:
- Do przodu deklaracji Enum CLR nie jest już obsługiwany.Nie istnieje żadne mapowanie.Po prostu jest on oznaczony jako błąd kompilacji.
__value enum status; // Managed Extensions: ok
enum class status; // new syntax: error
Rozpoznawanie przeciążenie między wbudowanych typów arytmetyczne i Object hierarchia klas została wycofana pomiędzy wersjami językowymi dwóch!Jako efekt uboczny teksty stałe CLR nie są już domyślnie są konwertowane na typy arytmetycznych.
W składni nowego wyliczenia CLR utrzymuje własny zakres, który nie jest w przypadku rozszerzeń zarządzanych.Wcześniej moduły wyliczające były widoczne w zakresie zawierającym wyliczenia.Moduły wyliczające są zhermetyzowana w zakresie wyliczenia.
Obiekt rodzaju są CLR tekstów stałych
Rozważmy poniższy fragment kodu:
__value enum status { fail, pass };
void f( Object* ){ Console::WriteLine("f(Object)\n"); }
void f( int ){ Console::WriteLine("f(int)\n"); }
int main()
{
status rslt = fail;
f( rslt ); // which f is invoked?
}
Dla programisty C++ macierzystego, naturalne odpowiedź na pytanie, których wystąpienia przeciążone f() jest wywoływana, jest f(int).Typ wyliczeniowy jest symboliczne stałą i uczestniczy w standardowych integralnej promocji, które w takim przypadku mają pierwszeństwo przed. I w rzeczywistości w zarządzane rozszerzenia to wystąpienie, do którego rozwiązuje wywołanie.To spowodowane szereg niespodzianek-nie użyliśmy je w macierzystym C++ samopoczucie — ale nam potrzebne do interakcji z istniejących ram BCL (Biblioteka klasy podstawowej), gdzie Enum jest klasą pośrednio pochodną Object.W Visual C++ projekt języka, wystąpienie f() wywoływany jest to, że z f(Object^).
Sposób Visual C++ wybrał wymuszenie to nie obsługuje niejawnej konwersji typu CLR enum i rodzajów arytmetycznych.Oznacza to, że dowolny przydział obiektu CLR typu enum na typ arytmetyczny wymaga jawne rzutowania.Tak więc na przykład, biorąc pod uwagę
void f( int );
jako formę przeciążone w wywołaniu zarządzane rozszerzenia
f( rslt ); // ok: Managed Extensions; error: new syntax
jest ok i wartość zawartą w ramach rslt jest niejawnie konwertowana na wartość całkowitą.W Visual C++, to wywołanie nie można skompilować.Poprawne tłumaczenie go, możemy wstawić operator konwersji:
f( safe_cast<int>( rslt )); // ok: new syntax
Zakres CLR typu tekstu stałego
Jedną ze zmian między w językach C i C++ było dodanie zakresu w obrębie obiektu portowego struct języka C++.W C struct jest po prostu agregacji danych nie obsługują interfejsu lub skojarzonego zakresu.To był dość radykalną zmianę w czasie i jest kwestią sporną dla wielu nowych użytkowników języka C++ pochodzących z języka C.Związek między macierzystym i CLR enum jest analogiczne.
W zarządzanych rozszerzeń podjęto próbę, do definiowania nazw słabo wtryskiwanego dla moduły wyliczające Enum CLR w celu symulacji braku zakresie w macierzystym enum.To okażą się skuteczne.Problem polega na tym, że powoduje to, że moduły wyliczające do wycieku do globalnego obszaru nazw, w wyniku trudno zarządzać konfliktów nazw.W nowych składni możemy dostosowane do innych języków CLR we wspieraniu zakresy w CLR enum.
Oznacza to, że każde niekwalifikowanych korzystanie z modułu wyliczającego CLR enum nie zostanie rozpoznany przez nowe elementy składni.Spójrzmy na przykład rzeczywistych.
// Managed Extensions supporting weak injection
__gc class XDCMake {
public:
__value enum _recognizerEnum {
UNDEFINED,
OPTION_USAGE,
XDC0001_ERR_PATH_DOES_NOT_EXIST = 1,
XDC0002_ERR_CANNOT_WRITE_TO = 2,
XDC0003_ERR_INCLUDE_TAGS_NOT_SUPPORTED = 3,
XDC0004_WRN_XML_LOAD_FAILURE = 4,
XDC0006_WRN_NONEXISTENT_FILES = 6,
};
ListDictionary* optionList;
ListDictionary* itagList;
XDCMake() {
optionList = new ListDictionary;
// here are the problems …
optionList->Add(S"?", __box(OPTION_USAGE)); // (1)
optionList->Add(S"help", __box(OPTION_USAGE)); // (2)
itagList = new ListDictionary;
itagList->Add(S"returns",
__box(XDC0004_WRN_XML_LOAD_FAILURE)); // (3)
}
};
Każdy z trzech bez zastrzeżeń używa nazwy modułu wyliczającego ((1), (2), i (3)) będą musiały być kwalifikowany w tłumaczeniu do nowych składni, aby skompilować kod źródłowy.Oto poprawne tłumaczenie oryginalnego kodu źródłowego:
ref class XDCMake {
public:
enum class _recognizerEnum {
UNDEFINED, OPTION_USAGE,
XDC0001_ERR_PATH_DOES_NOT_EXIST = 1,
XDC0002_ERR_CANNOT_WRITE_TO = 2,
XDC0003_ERR_INCLUDE_TAGS_NOT_SUPPORTED = 3,
XDC0004_WRN_XML_LOAD_FAILURE = 4,
XDC0006_WRN_NONEXISTENT_FILES = 6
};
ListDictionary^ optionList;
ListDictionary^ itagList;
XDCMake() {
optionList = gcnew ListDictionary;
optionList->Add("?",_recognizerEnum::OPTION_USAGE); // (1)
optionList->Add("help",_recognizerEnum::OPTION_USAGE); //(2)
itagList = gcnew ListDictionary;
itagList->Add( "returns",
_recognizerEnum::XDC0004_WRN_XML_LOAD_FAILURE); //(3)
}
};
Spowoduje to zmianę strategii projektowania pomiędzy pochodzący i wyliczenia CLR.Z wyliczenia CLR, utrzymanie skojarzonego zakresu w Visual C++, nie jest ani konieczne ani skuteczne do hermetyzacji deklaracji wyliczenia w klasie.Tego języka ewoluował w czasie cfront 2.0 w Bell Laboratories również dla rozwiązania problemu zanieczyszczenia Nazwa globalnego.
W oryginalnej wersji beta nowej biblioteki iostream przez Jerry Schwarz w Bell Laboratories, Jerry nie hermetyzacji wszystkie skojarzone, zdefiniowane dla biblioteki i typowe moduły wyliczające takich jak teksty stałe read, write, append, i tak dalej się to prawie niemożliwe dla użytkowników do kompilowania ich istniejącego kodu.Jednym rozwiązaniem byłby do modyfikacji nazwy, takie jak io_read, io_write, itp. Drugim rozwiązaniem byłby do modyfikacji języka przez dodanie zakresu do wyliczenia, ale nie było to możliwe w tym czasie.Środkowy rozwiązaniem było hermetyzacji enum w obrębie tej klasy lub klas hierarchii, gdzie zarówno nazwa tagu i moduły wyliczające wyliczenia wypełnić zasięgu klasy.) To znaczy motywacji do wprowadzania tekstów stałych w klasach, przynajmniej początkowo, nie było filozoficzne, ale praktyczne odpowiedzi na problem globalnego zanieczyszczenia obszaru nazw.
Z Visual C++ enum, nie ma już żadnych istotnych korzyści dla encapsulating wyliczenia w klasie.W rzeczywistości, jeśli spojrzeć na System obszarów nazw, zobaczysz że teksty stałe, klas i interfejsów zamieszkują w tej samej przestrzeni deklaracji.