static_cast w C++
Operator obsady to a operator jednoargumentowy co wymusza konwersję jednego typu danych na inny typ danych.
C++ obsługuje 4 typy rzutowania:
- Obsada statyczna
- Dynamiczna obsada
- Obsada stała
- Reinterpretacja obsady
W tym artykule skupiono się na szczegółowym omówieniu static_cast.
Obsada statyczna
Jest to najprostszy rodzaj rzutu, jaki można zastosować. To jest rzutowanie w czasie kompilacji . Wykonuje takie rzeczy, jak niejawne konwersje między typami (takie jak int na float lub wskaźnik na void*), a także może wywoływać jawne funkcje konwersji.
Składnia static_cast
static_cast < dest_type>(źródło);
Wartość zwracana przez static_cast będzie wynosić typ_docelowy.
Przykład static_cast
Poniżej znajduje się program C++ do implementacji static_cast:
C++
// C++ Program to demonstrate> // static_cast> #include> using> namespace> std;> // Driver code> int> main()> {> > float> f = 3.5;> > // Implicit type case> > // float to int> > int> a = f;> > cout < <> 'The Value of a: '> < < a;> > // using static_cast for float to int> > int> b => static_cast> <> int> >(f);> > cout < <> '
The Value of b: '> < < b;> }> |
Wyjście
The Value of a: 3 The Value of b: 3
Zachowanie static_cast dla różnych scenariuszy
1. static_cast dla prymitywnych wskaźników typu danych:
Wprowadźmy teraz kilka zmian w powyższym kodzie.
C++
// C++ Program to demonstrate> // static_cast char* to int*> #include> using> namespace> std;> // Driver code> int> main()> {> > int> a = 10;> > char> c => 'a'> ;> > > // Pass at compile time,> > // may fail at run time> > int> * q = (> int> *)&c;> > int> * p => static_cast> <> int> *>(&c);> > return> 0;> }> |
Wyjście
error: invalid 'static_cast' from type 'int*' to type 'char*'
Wyjaśnienie: Oznacza to, że nawet jeśli myślisz, że możesz w jakiś sposób przenieść konkretny wskaźnik obiektu na inny, ale jest to nielegalne, metoda static_cast nie pozwoli ci tego zrobić.
2. Konwersja obiektu za pomocą operatora konwersji zdefiniowanego przez użytkownika
static_cast może wywołać operator konwersji klasy, jeśli jest zdefiniowany. Weźmy inny przykład konwersji obiektu do i z klasy.
Przykład:
C++
// C++ Program to cast> // class object to string> // object> #include> #include> using> namespace> std;> // new class> class> integer {> > int> x;> public> :> > // constructor> > integer(> int> x_in = 0)> > : x{ x_in }> > {> > cout < <> 'Constructor Called'> < < endl;> > }> > // user defined conversion operator to string type> > operator string()> > {> > cout < <> 'Conversion Operator Called'> < < endl;> > return> to_string(x);> > }> };> // Driver code> int> main()> {> > integer obj(3);> > string str = obj;> > obj = 20;> > // using static_cast for typecasting> > string str2 => static_cast> (obj);> > obj => static_cast> (30);> > return> 0;> }> |
Wyjście
Constructor Called Conversion Operator Called Constructor Called Conversion Operator Called Constructor Called
Wyjaśnienie: Spróbujmy zrozumieć powyższy wynik linia po linii:
- Gdy obj tworzony jest wówczas wywoływany jest konstruktor, który w naszym przypadku jest jednocześnie Konstruktorem Konwersji (w przypadku C++14 zasady uległy lekkiej zmianie).
- Kiedy tworzysz ul poza obj , kompilator nie zgłosi błędu, ponieważ zdefiniowaliśmy operator konwersji.
- Kiedy zrobisz obj = 20 , w rzeczywistości wywołujesz konstruktor konwersji.
- Kiedy zrobisz str2 poza static_cast , jest bardzo podobny do string str = obj ; ale przy ścisłym sprawdzaniu typu.
- Kiedy piszesz obj = static_cast (30) , zamieniasz 30 na liczba całkowita używając static_cast.
3. static_cast dla dziedziczenia w C++
static_cast może zapewnić zarówno przesyłanie w górę, jak i w dół w przypadku dziedziczenia. Poniższy przykład ilustruje użycie static_cast w przypadku przesyłania w górę.
Przykład:
C++
// C++ Program to demonstrate> // static_cast in inheritance> #include> using> namespace> std;> class> Base> {};> class> Derived :> public> Base> {};> // Driver code> int> main()> {> > Derived d1;> > > // Implicit cast allowed> > Base* b1 = (Base*)(&d1);> > > // upcasting using static_cast> > Base* b2 => static_cast> (&d1);> > return> 0;> }> |
Wyjaśnienie: Powyższy kod skompiluje się bez żadnego błędu.
- Wzięliśmy adres d1 i jawnie wrzuciliśmy go do bazy i zapisaliśmy w b1.
- Wzięliśmy adres d1 i użyliśmy static_cast, aby rzucić go do bazy i zapisać w b2.
W powyższym przykładzie odziedziczyliśmy klasę bazową jako publiczną. Co się stanie, gdy odziedziczymy je jako prywatne? Poniższy przykład demonstruje, co następuje:
Przykład:
C++
// C++ program to demonstrate> // static_cast in case of> // private inheritance> #include> using> namespace> std;> class> Base> {};> class> Derived:> private> Base> {> > // Inherited private/protected> > // not public> };> // Driver code> int> main()> {> > Derived d1;> > > // Implicit type cast allowed> > Base* b1 = (Base*)(&d1);> > > // static_cast not allowed> > Base* b2 => static_cast> (&d1);> > return> 0;> }> |
Błąd czasu kompilacji:
[Error] 'Base' is an inaccessible base of 'Derived'
Wyjaśnienie: Powyższy kod będzie nie kompilować nawet jeśli odziedziczysz to jako chroniony .
Aby więc użyć static_cast w przypadku dziedziczenia, klasa bazowa musi być dostępna, niewirtualna i jednoznaczna.
4. static_cast do rzucania „do i z” wskaźnika pustki
Operator static_cast umożliwia rzutowanie dowolnego typu wskaźnika na wskaźnik typu void i odwrotnie.
Przykład:
C++
// C++ program to demonstrate> // static_cast to cast 'to and> // from' the void pointer> #include> using> namespace> std;> // Driver code> int> main()> {> > int> i = 10;> > void> * v => static_cast> <> void> *>(&i);> > int> * ip => static_cast> <> int> *>(v);> > cout < < *ip;> > return> 0;> }> |
Wyjście
10