Pure Virtual Function Called?
-
Hallo bIce!
Du interpretierst den Code nicht korrekt!int main() { //ich erzeuge zunächst eine Instanz der Klasse 'TMyClass1': TMyClass1 obj; //dann wird eine Kopie einer temporären Instanz der Klasse 'TMyClass2' //an 'obj' übergeben: obj.add(TMyClass2(&obj)); //Bem.: wobei diese übergebene Instanz per Pointer auf ihr Elternobjekt // zugreifen kann // (in etwa wie bei der Zuordnung von Kindknoten zu Elterknoten) }
Ich hab gerade festgestellt, dass der beschrieben Fehler unabhängig von der Bezeichnung der Routine 'add', ich könnte die Methode also auch 'bloedsinn()' nennen, und unabhängig vom darin ausgeführeten Code auftritt. Es müssen also die genutzten Klassen für den Fehler verantwortlich sein!
Nur wie kann denn ein Aufruf der folgenden Routine zu der Meldung "Pure Virtual Function Called' führen??? Ist mir echt schleierhaft!void bloedsinn(TClass2 obj) { <unwichtig> }
Grüße,
TS++
-
TS++ schrieb:
Hallo bIce!
Du interpretierst den Code nicht korrekt!int main() { ... //dann wird eine Kopie einer temporären Instanz der Klasse 'TMyClass2' //an 'obj' übergeben: obj.add(TMyClass2(&obj)); }
Bist Du Dir auch im Klaren darüber, dass diese temporäre Instanz nur für den Aufruf der Methode .add() existiert, dannach wird sie imho "gelöscht".
-
Ja, klar!
Die temporäre Instanz wird wieder gelöscht, logisch!
Nur die automatisch erzeugte Kopie, die per 'call_by_value' übergeben wird, die wird wiederum in den intern verwendeten Vector kopiert. Bleibt also dauerhaft bestehen! Mach dir also darüber keine weiteren Gedanken! Ich hab ja auch gerade gepostet, dass das Verwenden des Vectors innerhalb von 'add' in Bezug auf mein Problem unerheblich ist. Es kann mir bei der letzten stark abgespeckten Version also völlig egal sein, ob das übergebene Objekt dauerhaft besteht, oder nicht!Ich hab mal den Code folgendermaßen abgeändert:
void TMyClass1::add(TMyClass2& obj) { <unwichtig> }
=> lässt sich problemlos übersetzen, klar, und führt nicht wie vielleicht erwartet erneut zu dem erwähnten Fehler.
Es scheint also irgendwie damit zu tun zu haben, dass ich vorgebe, eine Kopie einer Instanz des Typs 'TMyClass2' zu übergeben.
Ich poste das Problem sicherheitshalber mal im C++-Forum. Vielleicht ist ja der Builder trotzdem nicht schuld. Falls Ihr mir aber trotzdem weiterhelfen könnt, bitte scheut nicht auch hier im Forum zu posten.Danke!
Grüße,
TS++
-
Und selbst diese Kopie, die beim Aufruf von add erzeugt wird, wird nach dem Verlassen gelöscht weil es kein dynamisch erzeugtes Objekt ist, und mit dem &-Operator wird eine Referenz übergeben.
-
TS++ schrieb:
Ich poste das Problem sicherheitshalber mal im C++-Forum.
Bitte nicht!
Dafür gibt's das Verschieben, was hiermit durchgeführt wurde.
-
@bIce:
Der genannte Vector ist ein Member!!!!!!
-
ich meine nicht den Vector sondern den Parameter.
-
Was verwendest Du intern für einen Vector? Irgendeinen
vector<Basisklasse von TMyClass2> ?
Falls das sowas ähnlich ist, dann geht Dir beim einfügen des Objekts wahrscheinlich der Anteil der abgeleiteten Klasse verloren, weil Du nur ein Objekt vom Typ der Basisklasse reinspeicherst, der Rest wird sozusagen abgeschnitten.
-
@bIce:
Um Gottes Willen!
Bitte google nach "STL" und informier dich über "std::vector". Der Vector ist sowas wie eine Kapselung eines dynamischen Arrays.@Jester:
Der Vector verfügt ganz billig über folgende Spezifikation:
vector<TMyClass2> myVector;Ausserdem ist der Vector garnicht das Problem. Ich könnte den gesamten Code aus 'add' auch rauslöschen. Die Parameterliste von 'add' scheint diesen Laufzeitfehler zu verursachen. Nur warum. Wie ich bereits erwähnt habe, tritt der genannte Laufzeitfehler bei einer Referenz nicht mehr auf. Seltsam!!??
Grüße,
TS++
-
Vielleicht wäre jetzt der richtige Zeitpunkt uns mal Deine Konstruktoren und Destruktoren zu offenbaren... meine Kristallkugel ist zur Zeit leider in Reparatur.
Möglicherweise ist Dein Beispiel zu stark vereinfacht um den Fehler noch aufzuzeigen. Trau uns mal etwas mehr zu!
-
warum haelt sich nur keiner an die regel: immer ein minimales compilierbares beispiel posten, dass den fehler noch offenbart. dabei findet man meist auch raus, worans liegt. aber bitte nicht mit bcb spezifischen klassen.
-
Ok, ich kümmer mich morgen drum!
Grüße,
TS++
-
TS++ schrieb:
@bIce:
Um Gottes Willen!
Bitte google nach "STL" und informier dich über "std::vector". Der Vector ist sowas wie eine Kapselung eines dynamischen Arrays.Ich weiß was ein vector ist, aber mal ne Frage zu dynamischen Arrays, kannst Du mal die ungekapselte Version präsentieren, ist echt interresant.
@Jester:
Der Vector verfügt ganz billig über folgende Spezifikation:
vector<TMyClass2> myVector;Ich bin davon ausgegangen das es so aussieht:
vector<TMyClass2*> myVector;
Da es aber nicht der Fall ist, ist auch das meiste davon was ich gesagt habe falsch. :p
-
Morgen!
bIce schrieb:
Ich weiß was ein vector ist, aber mal ne Frage zu dynamischen Arrays, kannst Du mal die ungekapselte Version präsentieren, ist echt interresant.
Wie SGI das exakte Innenleben des Vectors realisiert hat, kann ich dir so auf die Schnelle natürlich nicht erklären. Da müsstest du dir schon mal selbst den Quellcode zum vector ansehen.
Wenn du mal selbst ein dynamisch erweiterbares Array erstellen möchtest, so gibt es neben vielen anderen Ansätzen z.B. folgenden einfachen Ansatz:Dein Array wäre hierbei nichts weiter als ein dynamisch erzeugtes Pointer-Array, wobei dessen Pointer auf dynamisch erzeugte ContentObjekte zeigen. Möchtest du dem Array ein weiteres Element hinzufügen, so erzeugts du dynamisch ein neues PointerArray, übernimmst die Adressen aus dem alten Array, löscht das alte Array und hängst das neue ContentObjekt per Pointer an der letzten Stelle des neuen Pointerarrays ein. Beim Entfernen von Elementen kannst du nach dem gleichen Grundprinzip verfahren. Alles was du zu tun hast, is immer die bereits existierenden Adressen in einem neuen Array anzuordnen und überflüssige Adressen zu entfernen bzw. neue Adressen einzufügen.
(Ist natürlich nur ein recht einfacher Ansatz, aber immerhin recht zuverlässig und nicht all zu schwer realisierbar!)Was mein ursprüngliches Problem anbelangt, so war ich offensichtlich selbst schuld. Ich hab's jetzt! Ich bin mit dem Debugger nicht weit genug gegangen und hab somit verpasst, dass der Fehler tatsächlich durch den Destruktor des Objekts verursacht wird, das nur temporär in 'add' vorhanden ist. Im Vector wird ja eine Kopie dieses Objekts hinterlegt. Und exakt dieser Destruktor ruft über den Destruktor einer seiner Elternklassen die dort als abstrakt deklarierte Methode 'clear()' auf. 'clear()' wird in meiner Klassenhierarchie zwar in den entsprechenden Kindklassen implementiert, nur wenn der Methodenaufruf im Destruktor der Elternklasse stattfinden, nützt mir das natürlich wenig.
Was lernen wir daraus: Ruhig mal zu Ende Debuggen!Interessanterweise stellt der Compiler von VC bereits beim Linken fest, dass der Aufruf einer abstrakten Routine droht. Der BorlandCompiler erkennt das nicht. Er übersetzt das, wie bereits erwähnt, problemlos, linked ohne Schwierigkeiten und hat dann erst zur Laufzeit Probleme!
Na, ja. Jetzt weiss ich wenigstens woran ich bin!
Danke!
Grüße,
TS++