Zugriff auf Klasse über NULL Pointer
-
hi leute, sorry dass ich den thread nochmal raufhole aber ich hab hier was interessantes
Ich hab einfach mal meinem Freund
Scott Meyers (Kolumnist im C++ Report und Autor der "Effective" Reihe) geschrieben, als Antwort bekam ich prompt (SOGAR IN DEUTSCH!!!):
Danke. Es freut mich, daß Sie meine Bücher nützlich gefunden haben.
I've discovered some strange behavior with null pointer to classes - but I
could imagine you already know that
So, if I call a normal member function of a class via a null-pointer to the class, the function is handled like a static function of the class.
Is this behavior undefined, not portable, compiler dependent?Es ist in prinzip nicht möglich, ein null this-pointer zu haben, weil es nicht möglich sein sollte, ein Mitgliederfunktion ohne ein Objekt aufzurufen. Deswegen ist solche Code bestimmt nicht portable.
I don't think that it is defined in the c++ standard, but why does MS Visual C++ and g++ support it? Even in the MFC there are constructs like:
if (this == NULL)
> return NULL;
else
> return m_hWnd;Ich habe keine Ahnung, warum solche Code in MFC besteht, aber mir is MFC ein Geheimnis
Scott
Also hier haben wirs nochmal von einem Profi erklärt.
greetz
-
operator void schrieb:
Dass es Sinn machen kann, zeigt der MS-Code doch.
Ich habe ja einen bösen Verdacht wofür die Konstruktion eingeführt wurde
dynamic_cast<child*>(pointertobase)->DoDirtyStuff()
Wenn so bei Winzigweich Fehler abgefangen werden dürfte so einiges klar werden
-
joX schrieb:
operator void schrieb:
Dass es Sinn machen kann, zeigt der MS-Code doch.
Ich habe ja einen bösen Verdacht wofür die Konstruktion eingeführt wurde
dynamic_cast<child*>(pointertobase)->DoDirtyStuff()
Wenn so bei Winzigweich Fehler abgefangen werden dürfte so einiges klar werden
Also da bin ich dann aber doch für:
try{ dynamic_cast<child&>(*pointertobase).DoDirtyStuff() }catch(bad_cast&){ ... }
Denn wie stelt man beim ersten fest ob es nicht geklappt hat oder nicht?
-
Man sollte prüfen ob ein null-Pointer zurückgegeben wurde.
-
Irgendwer schrieb:
Also da bin ich dann aber doch für:
try{ dynamic_cast<child&>(*pointertobase).DoDirtyStuff() }catch(bad_cast&){ ... }
Denn wie stelt man beim ersten fest ob es nicht geklappt hat oder nicht?
Shlo schrieb:
Man sollte prüfen ob ein null-Pointer zurückgegeben wurde.
Ich dachte das standard Verhalten von dynamic_cast sein einen NUll-Pointer zurueck zu geben und nicht eine Exception zu schmeißen. Und die herzallerliebeste MS-Implementation
HWND CWnd::GetSafeHwnd() { if(this == NULL) return NULL; else return m_hWnd; }
fragt den Null-Pointer (zwar nicht ISO konform) ja schon irgendwie ab :D.
-
Ok, die Lösung ist zwar nicht portabel, aber das war auch nie Anforderung der MFC. Die wird ausschließlich mit dem MS Compiler verwendet, und das war's. Gut, Borland und Watcom (und vielleicht ein paar andere) haben sie damals auch in angepassten Versionen gebundled, aber das ist ihr Problem.
Ich glaub dynamic_cast wird nicht viel verwendet in der MFC, weil's das zu der Zeit noch gar nicht gegeben hat. Aber so wie man für "kein HWND" einfach 0 übergibt, so macht man's jetzt mit "kein CWnd" und NULL. Praktisch ist die GetSafeHWND Schreibweise doch. Wie sie implementiert ist, ist Sache des Compilerherstellers und sollte nicht dein Problem sein.
In jeder x-beliebigen Runtime Library jedes x-beliebigen C/C++ Compilers stecken haufenweise ähnliche oder noch viel schlimmere Schweinereien, aber solang's funktioniert, ist ja nieman damit geschadet.
Oder schau dir mal C++Builder/VCL an. Das geht's wirklich wüst zu, nicht so lächerliche Kleinigkeiten wie this==0!
-
joeX schrieb:
Ich dachte das standard Verhalten von dynamic_cast sein einen NUll-Pointer zurueck zu geben und nicht eine Exception zu schmeißen.
Nicht ganz, bei einem Pointer-Cast wird ein null-Zeiger zurückgegeben, bei einem Referenz-Cast dagen wird std::bad_cast geworfen, da eine Referenz niemals null sein kann.
-
Und deshalb ist:
dynamic_cast<child&>(*ptr).foo();
besser als:
if(dynamic_casr<child*>(ptr)->foo()) static_cast<child*>(ptr)->foo(); else //error...
Oder jedliche compiler spezifischen Wrapper.
-
Wenn ich einen Pointer habe, dann arbeite ich auch weiterhin mit einem Pointer:
if (A* p = dynamic_cast<A*>(pb)) p->foo();
Deshalb kann man allgemein nicht sagen, das dies oder das besser sei.
-
Shlo schrieb:
Deshalb kann man allgemein nicht sagen, das dies oder das besser sei.
Exakt, die Semantik ist naemlich total verschieden.
Den Referenzen-Cast nimmt man dann, wenn man sich sicher ist, dass der Cast erfolgreich sein wird und ein Fehlschlagen eine Ausnahme ist, die theoretisch nicht vorkommen sollte (wobei bei sowas ein checked_cast nicht besser waere). Wenn man den Pointer-Cast macht, dann prueft man meisstens ob es wirklich der richtige Typ ist - man geht also davon aus, dass der Cast durchaus fehlschlagen kann und reagiert dementsprechend darauf.
-
wo liegt eigentlich der sinn im reference cast?
ist damit irgendwas möglich, was sonst nich möglich wär?
-
otze schrieb:
wo liegt eigentlich der sinn im reference cast?
Was spricht gegen ihn?
Du verwendest ihn, stattif(!(p=dynamic_cast<Derived*>(base))) throw Error();
das ist doch durchaus sinnvoll
-
kann man mit dem reference cast von ner baseklass zu ner referenz auf nen derived casten?
ok, daran hab ich net gedacht^^
-
otze schrieb:
kann man mit dem reference cast von ner baseklass zu ner referenz auf nen derived casten?
ok, daran hab ich net gedacht^^
Genau für diese Möglichkeit hat man den dynamic_cast doch eingebaut.
Edit:
Vergesst mein Posting, habe vergessen, dass das nen alter Thread ist