Jestem początkującym C ++ i czytam Bjarne Stroustrup's Programming: Principles and Practice Using C ++ .
W sekcji 3.9.2 Niebezpieczne konwersje , wspomniał autor
Gdy inicjalizator jest literałem liczby całkowitej, kompilator może sprawdzić rzeczywistą wartość i zaakceptować wartości, które nie oznaczają zawężenia:
int char b1 {1000}; // error: narrowing (assuming 8-bit chars)
Zdziwi mnie ta deklaracja. Używa dwóch typów ( int
i char
). Nigdy wcześniej nie widziałem takiej deklaracji w Javie i Swifcie (dwóch językach, które stosunkowo dobrze znam). Czy to pomyłka czy prawidłowa składnia C ++?
float char
to kolejny przydatny typ, szczególnie w basenach. Niektóre są wyposażone w uchwyt na piwo.Odpowiedzi:
To błąd w książce. To nie jest prawidłowa deklaracja C ++, nawet bez rzekomej konwersji zawężającej.
Nie ma o tym wzmianki w żadnej z errat na stronie Bjarne Stroustrupa (czwarty druk i wcześniejsze), co jest dziwne. To wystarczająco jasny błąd. Wyobrażam sobie, że skoro jest to skomentowane,
//error
niewiele osób zauważy błąd w samej deklaracji.źródło
char b1 {1000};
(ponieważ spowodowałoby to błąd wspomniany w komentarzu). Chyba palce Bjarne'a były zmęczone tego dnia.int
tam dodatkowy ! :-)Książka jest zła.
Sekwencja tokenów
int char b1{1000};
nie jest poprawna semantycznie C ++.Próbujesz zadeklarować
b1
więcej niż jeden typ, co nie ma sensu.źródło
To jest złe. W C / C ++ deklaracje wielu typów można uzyskać za pomocą unii. Na przykład:
union { int i; char c; } var; var.i = 42; /* OR */ var.c = ‘c’;
Pamięć jest taka sama, więc .c i .i są po prostu uchwytami typu dla tej samej wartości.
źródło
To jest błąd w składni C / C ++. Oprócz
union
s (patrz odpowiedź @Alex), istnieje sposób w C ++ na przechowywanie tylko jednego z dostępnych typów o nazwiestd::variant
(type-safe union):#include <variant> #include <string> int main() { std::variant<int, float> v, w; v = 12; // v contains int int i = std::get<int>(v); w = std::get<int>(v); w = std::get<0>(v); // same effect as the previous line w = v; // same effect as the previous line // std::get<double>(v); // error: no double in [int, float] // std::get<3>(v); // error: valid index values are 0 and 1 try { std::get<float>(w); // w contains int, not float: will throw } catch (std::bad_variant_access&) {} std::variant<std::string> v("abc"); // converting constructors work when unambiguous v = "def"; // converting assignment also works when unambiguous }
źródło