Seltsam: Pointer mit X.sth() UND X->sthElse()
-
Bashar schrieb:
Man kann den -> Operator überladen:
struct A { void foo() { cout << "A::foo"; } }; class B { A* a; public: // ctor/dtor bitte selbst dazudenken void foo() { cout << "B::foo"; } A* operator->() { return a; } }; ... B b; b.foo(); // -> "B::foo" b->foo(); // -> "A::foo"
...
OK, "ich-nix-raffen", Teil II. Warum funktioniert das? Ich meine, in B existiert ein Zeiger auf A, nirgendwo wird ein A-Objekt instantiiert, und trotzdem wird korrekt "A::foo" ausgegeben. Nicht mal mit Compiler-Warnung, und das vollkommen ohne die Klasse A zu instanziieren (ich habs mit struct UND Klasse eben getestet, es funktioniert). (Ausserdem ist die Methode nicht statisch, wobei das in C++ und Java vermutlich zwei verschiedenen Dinge sind) ... .
Also, warum funktioniert gerade dieses Beispiel? (Ist vielleicht ne dumme Frage, aber es ist eine :))
-
Das ist halt C++. Das geht deshalb weil "this" von A hier nicht verwendest wird...
Änderst Du A nach
struct A { void foo() { std::cout << "A::foo" << m_i; } int m_i; };
oder
struct A { virtual void foo() { std::cout << "A::foo"; } };
so geht es nicht...
-
Jochen Kalmbach schrieb:
Das ist halt C++. ...
Das hast du schoen gesagt
Ausserdem danke fuer eure schnellen Antworten! Es ward Licht in meinem Schaedel ...
-
Jochen Kalmbach schrieb:
Das ist halt C++. Das geht deshalb weil "this" von A hier nicht verwendest wird...
Änderst Du A nach
struct A { void foo() { std::cout << "A::foo" << m_i; } int m_i; };
oder
struct A { virtual void foo() { std::cout << "A::foo"; } };
so geht es nicht...
Sehe ich das richtig, daß es nicht gehen würde weil man mit:
this->m_i
oder
bei einer Ableitung dann indirect this->foo
nicht mehr überlagern könnte?
-
@Axel++:
nirgendwo wird ein A-Objekt instantiiert
Das sollte in dem "selbstgedachten" Konstruktor passieren.
Der Code läuft "ausnahmsweise" auch so, und hat nix mit dem überladenen operator-> zu tun (s.u.)_com_ptr_t soll sich wie ein Zeiger (auf ein COM-Interface) verhalten, aber noch zusätzliche Aufgaben übernehmen (in deinem Fall die COM-Referenzzählung mittels AddRef und Release). Das ist die "netteste" Anwendung von überladenen Operatoren: einen neuen Typ zu schaffen, der sich wie ein eingebauter Typ verhält.
Du kannst fast alle Operatoren überladen (was nicht heiußt das du es immer solltest). Was wirklich nicht geht ist z.B. operator .() (Memberzugriff) - mehr Infos unter http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/overl_9.asp
---------------------
Das folgende läuft auch ohne Fehlermeldung, obwohl es eigentlich falsch ist:
struct A { void foo() { cout << "A::foo" << endl; } }; int main() { A * a; // uninitialisiert a->foo(); }
Weder der Methodenaufruf noch die Methode A::foo greifen auf die Instanz zu, somit greift auch niemand auf den uninitialisierten Zeiger zu.
-
Man kann es natürlich schon überlagern... nur würde der "this"-Zeiger halt ins niergendwo zeigen und somit (in den meisten Fällen) eine Exception werfen...
-
Also bräuchte man einen Konstruktor, was das überlagern wieder sinnfrei machen würde, da nun "this" die Überlagerung wäre?
-
codeman schrieb:
Also bräuchte man einen Konstruktor, was das überlagern wieder sinnfrei machen würde, da nun "this" die Überlagerung wäre?
????
Einen Konstruktor brauchst Du nur um die Member-Variablen zu initialisieren (geht leider nicht inline wie in C#). Das hat aber gar nichts mit dem überlagern zu tun.
-
wovon redet ihr grad??
-
Ich weiss auch nicht