Objektzugriff per Pointer
-
Hi,
ich hab folgendes Problem.
Ich möchte einer Funktion einen Basispointer übergeben, welcher dann auf ein Objekt gesetzt wird.
Nachdem die Funktion beendet wurde, soll der übergebene Pointer weiterhin auf das Objekt zeigen, auf das er in der Funktion gesetzt wurde.
Leider ist der übergebene Pointer nach der Funktion immer ungültig
Hab ich warscheinlich schlecht erklärt, aber vielleicht hilft der Code ein wenig...Beispiel:
class TBasis {}; class TAbgeleitet {}; // Speichert die Objekte std::vector<TBasis*> objectVector; void searchObject(TBasis* pointer) { // Hier die Suchkriterien... // Pointer auf das gefundene Objekt setzen // Hier ist "pointer" noch gültig pointer = objectVector[...]; } int main(void) { // Pointer der auf das gefundene Objekt zeigen soll TAbgeleitet* p = 0; // Suche das passende Objekt heraus und setze "p" auf das Objekt searchObject(p); // p ist hier leider immer 0! if(p == 0) throw ""; // ... }
Der Code ist natürlich stark vereinfacht, aber das Prinzip wird hoffentlich deutlich.
Wie schaffe ich es, das der Pointer, der der Funktion übergeben wurde, nach der Funktion noch gültig ist?Die Funktion könnte natürlich das gefundene Objekt zurückliefern, allerdings würde dann sowas nicht mehr funktionieren:
//... // Hier motzt der Compiler, da TAbgeleitet* nicht mit TBasis* initialisiert werden kann! TAbgeleitet* p = searchObject();
Leider weiß ich nicht mehr weiter...
Bastian
-
Das liegt daran, das für die Funktion eine neue Kopie für den Zeiger erstellt wird, die nur in der Funktion existiert. Beispiel:
#include <iostream> void Foo(int* p) { std::cout << "Adresse innerhalb Foo: " << &p; } int main() { int* p; std::cout << "Adresse außerhal Foo: " << &p << std::endl; Foo(p); }
Am einfachsten löst du dies mit einer Referenz:
#include <iostream> void Foo(int*& p) { std::cout << "Adresse innerhalb Foo: " << &p; } int main() { int* p; std::cout << "Adresse außerhal Foo: " << &p << std::endl; Foo(p); }
mfg.
-
joomoo schrieb:
Am einfachsten löst du dies mit einer Referenz:
nicht in diesem fall.
Die Funktion könnte natürlich das gefundene Objekt zurückliefern, allerdings würde dann sowas nicht mehr funktionieren:
//... // Hier motzt der Compiler, da TAbgeleitet* nicht mit TBasis* initialisiert werden kann! TAbgeleitet* p = searchObject();
das ist auch ganz klar. nicht jedes TBasis-Objekt ist notwendiger ein subobjekt eines TAbgeleitet objekts. würde der compiler diese zuweisung einfach so erlauben, hätten wir ein großes loch im typsystem. searchObject() weiß nichts von TAbgeleitet - kann folglich also nicht selbst garantieren, dass das ergebnis ein TAbgeleitet ist (wenn es das könnte, gäbe es keinen grund, nicht gleich TAbgeleitet zurückzugeben). hier muss also ein cast her, um dem compiler mitzuteilen, dass wir wissen und voraussetzen, dass das funktionsergebnis tatsächlich vom richtigen typ ist - oder wir können den compiler anweisen, das für uns herauszufinden, vorausgesetzt, TBasis ist polymorph. in letzterem falle setzen wir dynamic_cast ein, sonst static_cast. also
TAbgeleitet* p = static_cast<TAbgeleitet*>(searchObject());
hier liegt es in unserer verantwortung, dafür zu sorgen, dass da tatsächlich ein TAbgeleitet objekt ist, andernfalls ist das ergebnis undefiniert. mit einer veränderten parameterübergabe zu hantieren ist herumdoktern an symptomen und wird das zugrundeliegende problem nicht lösen, sondern höchstwahrscheinlich nur undefiniertes verhalten produzieren.
-
Hi joomoo,
da hast du recht, damit ist das Problem des ungültigen Pointers behoben.
Allerdings klappt das nicht mit abgeleiteten Klassen:
Hier mal mein Beispiel:#include <vector> #include <iostream> class TBasis { public: virtual void hallo(){ std::cout << "TBasis sagt Hallo!\n"; } }; class TAbgeleitet : public TBasis { public: virtual void hallo(){ std::cout << "TAbgeleitet sagt Hallo!\n"; } }; std::vector<TBasis*> objVector; void test(TBasis*& b) { b = objVector[0]; } int main(int argc, char* argv[]) { objVector.push_back(new TAbgeleitet()); TAbgeleitet* a; test(a); a->hallo(); }
Da gibt's bei mit folgenden Fehler:
Fehler: initializing non-const `TBasis *&' with `TAbgeleitet *' will use a temporary
Somit bin ich als Funktionsargument auf TAbgeleitet*& festgelegt.
BastianEDIT: camper war schneller