Dlaczego statyczna obsada umożliwia poduszkę lub dnie pomiędzy wskaźnikami do obiektów pochodzących lub podstawy jak poniżej, ale w przypadku odlewania między char * a INT * lub odwrotnie Int * do Char *, istnieje błąd kompilacji?

Odlewanie między różnymi wskaźnikami do obiektów jest równie zły, wierzę.

// compiles fine
class Base {};
class Derived: public Base {};
Base * a = new Base;
Derived * bc = static_cast<Derived*>(a);

// Gives an invalid static cast error during compilation
char charVar = 8;
char* charPtr = &charVar;
int* intPtr = static_cast<int*>(charPtr);
1
Engineer999 4 czerwiec 2018, 19:14

3 odpowiedzi

Najlepsza odpowiedź

C ++ jest silnie zorientowany na wydajność. Tak długo, jak bardzo istnieje kilka przypadków użytkowania, aby uzyskać wydajność, C ++ pozwoli Ci to zrobić. Rozważmy std::vector: Jasne, istnieje bezpieczny dostęp do funkcji at, który sprawdza się w zakresie. Ale jeśli wiesz, że twoje indeksy są w zasięgu (np. W pętli do pętli), sprawdzania te sprawdza to tylko martwa waga. Więc dodatkowo otrzymujesz (mniej bezpieczny) operator[], który po prostu pomija te kontrole.

Podobnie, jeśli masz wskaźnik typu Base, może być w rzeczywistości, wskaż obiekt typu Derived. W razie wątpliwości, byłbyś dynamic_cast z Base* do Derived*. Ale to przychodzi z jakimś nad głową. Ale jeśli wiesz w 100% na pewno (przez cokolwiek oznacza ...) Co faktycznie jest substablasty, czy chciałbyś tego nad głową? Ponieważ istnieje naturalny (nawet ukryty!) W drodze Derived* do Base*, chcemy mieć trochę niski koszt.

Z drugiej strony nie ma takiego naturalnego odlewu między wskaźnikami całkowicie niepowiązanych typów (takich jak char i int lub dwie niepowiązane klasy), a tym samym nie tak niski sposób wstecz (w porównaniu z {{{ Oczywiście X2}}, który nie jest dostępny, oczywiście). Jedyny sposób na przekształcenie między reinterpret_cast.

Właściwie Reinterpret_cast nie ma żadnych kosztów, po prostu interpretuje wskaźnik jako inny typ - ze wszystkimi ryzykami! A reinterpret_cast nawet może się nie powieść, jeśli zamiast tego jest static_cast (prawo, aby zapobiec pytaniu "Dlaczego nie tylko używać ..."):

class A { int a; };
class B { };
class C : public A, public B { };

B* b = new C();
C* c = reinterpret_cast<C*>(b); // FAILING!!!

Od widoku układu pamięci, C wygląda tak (nawet jeśli jest ukryty od ciebie):

class C
{
    A baseA;
    B baseB; // this is what pointer b will point to!
};

Oczywiście otrzymamy przesunięcie podczas odlewania między C* i B* (albo w kierunku), który jest uważany za oba static_cast i dynamic_cast, ale nie przez {{x4 }} ...

2
Aconcagua 4 czerwiec 2018, 17:21

Dlaczego Static_cast pozwala na upadek ...

Nie ma powodu, aby zapobiec przysmakom. W rzeczywistości, poinformowany wskaźnik jest nawet niejawnie zamienialny na wskaźnik podstawowy - nie jest konieczny (z wyjątkiem zawiłych przypadków, w których istnieje wiele baz samego typu). Obiekt klasy pochodnej zawsze zawiera obiekt klasy podstawowej.

Upcasting jest szczególnie przydatny, ponieważ umożliwia polimorfizm środowiska wykonawczego poprzez wykorzystanie funkcji wirtualnych.

lub w dół między wskaźnikami do obiektów pochodzących lub podstawy jak poniżej

Wskaźnik podstawy może wskaż obiekt podstawy obiektu pochodnego, w konsekwencji poduszki. Jak na przykład tutaj:

Derived d;
Base *b = &d;

Są przypadki, w których możesz uzyskać dostęp do członków obiektu pochodnego, że jesteś wskazany. Obsada statyczna umożliwia to możliwe bez kosztów informacji o czasie pracy.

Nie jest ogólnie możliwe, aby kompilator dowiedział się (w czasie kompilacji) betonowy typ spiczasty obiektu (tj. Czy wskaźnik wskazuje na obiekt podrzędny, a jeśli to robi, jaki jest typ obiektu kontenera). Obowiązkiem programistę jest spełnienie spełnienia wymagań odlewów. Jeśli programator nie może udowodnić poprawności, pisząc statyczną obsadę jest błędem.

2
eerorika 4 czerwiec 2018, 17:15

To dlatego, że to, co próbujesz zrobić, to reinterpretacja - dla której jest {{x0 }} operator. {{X1}

  1. Jeśli New_type jest wskaźnikiem lub odniesieniem do niektórych klasy D, a rodzaj wyrażenia jest wskaźnikiem lub odniesieniem do swojej wirtualnej bazy b, Static_cast wykonuje downcast. Ta obniżka jest źle utworzona, jeśli b jest niejednoznaczna, niedostępna lub wirtualna baza (lub podstawa wirtualnej bazy) D. Taka statyczna_cast nie sprawdza się, aby zapewnić, że typ środowiska wykonawczego obiektu jest faktycznie D i może być używany tylko Bezpiecznie, jeśli ten wstępny jest zagwarantowany przez inne środki, takie jak przy wdrażaniu polimorfizmu statycznego. Safe Downcasta może być wykonane z dynamicznymi_cast.

Widzieć:

Kiedy należy używać static_cast, dynamic_cast, const_cast i reinterpret_cast?

Szczegółową dyskusję, kiedy używać każdego operatora odlewu.

0
einpoklum 4 czerwiec 2018, 16:51