Rückgabe Objekt einer abgeleiteten Klasse über einen Zeiger seiner abstrakten Basis-Klasse
Ich muss ein Programm schreiben, welches in einer seine Funktion zurückkehren wird, eine abgeleitete Klasse, die über eine abstrakte Basisklasse, also, wenn die Klasse wieder zu den wichtigsten der Zugriff auf die abgeleitete Klasse mit virtuellen Methoden.
Bitte beachtet, dass ich nichts ändern kann im Hauptprogramm, da ich nicht das eine es zu schreiben.
#include<iostream>
using namespace std;
class A
{
private:
public:
virtual void DoIt(void)=0;
A(void){};
~A(void){};
};
class B:
public A
{
private:
int Num;
public:
virtual void DoIt(void){Num=7;cout<<"its done";};
B(void){};
~B(void){};
};
A& returnValue(void)
{
B item;
return item;
}
void main()
{
A& item=returnValue();
item.DoIt();
}
Wenn ich versuche zu laufen, das die Letzte Zeile bricht der build sagen, dass DoIt
ist eine pure virtual Funktion call.
irgendwelche Ideen?
- Ist die Signatur von
returnValue
behoben? Sie sollte nicht wieder eine Referenz auf eine lokale variable. - es ist nicht fixiert. ich kann entscheiden, wie retrun mein Wert.
- Das ist das Problem. Reservieren
item
dynamisch (B* item = new B;
). Dann wieder ein Zeiger oder eine Referenz darauf. Das sollte es beheben. - Welchen compiler benutzt du? ideone kein problem kompilieren, aber es verursacht einen runtime error.
- das wird sicher das problem beheben, aber es wird zu erhöhen eine andere: wie lösche ich den Speicher?
- Ja, das stimmt so nicht wieder einen Verweis. Gibt einen Zeiger. Und dann können Sie es löschen wenn Sie möchten. ODER noch besser, verwenden Sie ein smart-pointer.
- ich bin mit visal 2012, aber es läuft evtl. auf meiner Uni-compiler auf dem unix-system.
- wie kann ich es löschen whene immer ich will? ich habe keine contrual über den main. was ist ein smart-pointer?
- stackoverflow.com/questions/106508/...
- Ich denke, man sollte eine gewisse Zusammenarbeit mit den Menschen, die schreiben Sie den rest des Codes. Sie sollten wissen, dass Sie löschen müssen. Dokument die Funktion, die Sie wissen lassen,....(wenn nicht mithilfe der smart-Pointer.)
- wünschte, ich könnte, kann ich nicht sagen, Sie wie eine Sache ist, da es ist eine Aufgabe der Universität. dies ist das erste mal höre ich über "smart pointer" ich werde versuchen zu lernen, seine Verwendung und vielleicht wird es funktionieren. gibt es eine Möglichkeit, es zu benutzen mit der Verwendung der Vorlage? es ist nicht erlaubt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sind Sie wieder, eine Referenz auf eine lokale variable, die zerstört wird, wenn der Aufruf in
returnvalue
abgeschlossen ist. Stattdessen versuchen Sie Folgendes:Eine bessere Lösung ist die Rückkehr ein smart pointer und lassen Sie die Menschen, die Aufrechterhaltung der main-Funktion nehmen Sie die Verantwortung für die Lebensdauer des Objekts zurückgegeben, die von
returnvalue
:Den
item
Sie zurück inreturnValue()
ist erst dann zerstört, wenn die Funktion beendet. Was diese Funktion zurückgibt, ist Verweis auf Objekt zerstört. Sie brauchen, um zu bewahren das Objekt irgendwie. Zum Beispiel:oder:
BTW erhalten Sie "pure virtual function call" - Fehler durch Zufall: Durch die Zeit, die Sie rufen
item.DoIt()
die virtual table pointer wird geändert (durchB
's destructor) zu Punkt zuA
's virtuelle Mitglieder, und rein virtuelle Funktionen bekommen, drückte auf eine Funktion, die anzeigt, dieser Fehler. Aber Sie sind nicht garantiert, um es zu erreichen, da die virtuelle Tabelle Zeiger befindet sich bereits in befreit stack-Speicher. Der compiler möglicherweise wiederverwendet dieser Speicher für etwas ganz anderes.Gibt es ein paar Probleme hier. Der Hauptgrund ist, dass die
item
imreturnValue
wird out-of-scope sofort, so dass es nicht mehr ein Objekt in der main auf, die zu nennenDoIt
. Wegen diesem gibt es keine Objekte, mit denen Folgen des vererbungsbaums. Dies erklärt auch die Fehlermeldung, die Sie erhalten (item
im main nicht vom Typ B mehr, weil es nicht existiert). Ich bin überrascht, dass es nicht einfach Abstürzen, aber.Um dieses problem zu beheben, werden Sie wollen, um entweder eine Kopie (pass-by-value statt Referenz) des Objekts oder das Objekt auf dem heap (und einen Zeiger übergeben werden). Für letzteres:
Weiteres Problem ist, dass Sie virtuelle Funktionen aber nicht-virtuellen Destruktoren! Dies kann ein ernsthaftes Problem. Sie wollen beide
virtual ~A(void){};
undvirtual ~B(void){};
um sicher zu sein.new
-ed, es kann löschen, es wenn es fertig ist. Wenn Sie die Funktion aufrufenreturnValue
erwartet eine Referenz, dann ist entweder (a) es denkt, das Objekt ist statisch oder (b) es denkt, das Objekt ist im Besitz etwas anderes. Wenn (b), dann ist das etwas anderes, nur nicht das löschen.