Fragen zu vector<Klasse*>

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
nerem
Beiträge: 15
Registriert: 15.03.2012, 22:18

Fragen zu vector<Klasse*>

Beitrag von nerem »

Hey zusammen,
nach jahrelanger Abwesenheit, was Programmierung anbelangt, versuche ich zur Zeit wieder etwas ins Programmieren zu kommen, alte Kenntnisse aufzufrischen und neue Kentnisse zu erlangen. Und prompt stellt man sich die eine oder andere Frage.
Und zwar geht es darum, in einem Vektor Zeiger zu speichern, um sowohl Basis- als auch abgeleitete Klassen sammeln zu können. Nun stellt sich die Frage, ob ich folgendes machen kann (compilieren tut es, so weit ich das ausprobieren konnte, tut es auch es "soll"):

Code: Alles auswählen

#include <iostream>
#include <vector>

using namespace std;

class Base
{
public:
	virtual void f() { cout << "Base \n"; }
};

class Derived : public Base
{
public:
	virtual void f() { cout << "Derived \n"; }
};

int main()
{
	vector<Base*> BVector;
	int a;
	do
	{
		cin >> a;
		Derived Abgeleitet;
		BVector.push_back(&Abgeleitet);
		cout << BVector.size() << endl;
		cout << &BVector[BVector.size() - 1] << endl;
	} while (a != 0);

	return 0;
}
Im Internet finde ich immer

Code: Alles auswählen

BVector.push_back(new Derived());
oder analog mit Smartpointern realisiert. Brauche ich wirklich new? Mache ich in meinem Beispiel oben etwas falsch? Intuitiv würde ich sagen, dass ich in meinem Vektor lauter Zeiger sammle, die auf kein Objekt mehr zeigen (da Abgeleitet jedes mal gelöscht wird).
Wenn ich danach allerdings via

Code: Alles auswählen

BVector[0]->f();
zugreife, funktioniert das. Wieso?

Kurz gesagt: Brauche ich new um dynamisch Objekte zu einem Vektor von Zeigern hinzuzufügen oder nicht?

Über Hilfe würde ich mich sehr freuen!
Beste Grüße
Felix
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Fragen zu vector<Klasse*>

Beitrag von Schrompf »

Kurz geantwortet: Nö. Ein std::vector<PointerType> tut genau das, was drauf steht: er speichert Zeiger. Zeiger sind Speicheradressen, also banale Zahlen, die die Hardware über mehrere Zwischenschritte auf kleine Ladungsträger im RAM-Riegel abbilden kann. Das push_back(&object), was Du da tust, nimmt also die Adresse des Objekts und schreibt die in den vector.

Danach wird das Objekt zerstört, der Zugriff auf das Objekt mittels des Zeigers ist also theoretisch illegal. Praktisch passiert hier aber erstmal nicht viel Schlimmes, da Deine Beispielklasse in ihrem Destruktur nix tut und damit die Bytes, wie sie an der Stelle im Speicher liegen, unverändert da weiter liegen bleiben. Das ist also ein Crash, der nur aus Versehen nicht sichtbar ist. Ganz üble Sache in echtem Code, aber Du hast das ja explizit zu Lernzwecken so geschrieben und bist Dir der Folgen bewusst, also will ich da nicht meckern.

Dein zweites cout ist aber definitiv Humbug. Du holst Dir dort das letzte Element im vector (was viel kürzer mit der Methode back() geht) und gibst dann die Adresse davon aus. Also die Adresse der Adresse, ein Doppelzeiger. Das ist wahrscheinlich nicht, was Du sehen wolltest. Wenn Du stattdessen das Objekt selbst ausgibst, also die im vector gespeicherte Adresse, wirst Du sehen, dass die immer die selbe ist. Weil das Objekt immer an der selben Stelle im Stack neu angelegt und wieder zerstört wird.

Kleinkram zum Rest des Codes:

- Benutze C++11 oder neuer. Das bedeutet hier konkret: markiere f() in der Ableitung mit "override", um dem Compiler zu sagen, dass Du an der Stelle eine Methode der Basisklasse überschreibst. Dann kannst Du auch das virtual vor der überschriebenen Funktion weglassen.
- Vermeide Großschreibung für Instanzen, benutze sie nur für Typen. Eine Klasse darf also Base heißen, die Instanz BVector sollte aber besser bvector oder sowas heißen.
- Benutze Einrückung :-)
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
nerem
Beiträge: 15
Registriert: 15.03.2012, 22:18

Re: Fragen zu vector<Klasse*>

Beitrag von nerem »

Hey,
Vielen Dank für die ausführliche Antwort.
Einrückungen verwende ich, scheint hier beim rüberkopieren verloren gegangen zu sein.
Override ist mir bekannt, aber danke für die Erinnerung :)
Jetzt ist mir das mit der Ausgabe auch klar, ich hatte mehrere Ausgaben in meiner ursprünglichen Version und dachte, dass ich tatsächlich immer verschiedene Adressen habe. Aber das lag dann also daran, dass ich die Adresse des Zeigers auf den Zeiger ausgegeben habe?!

Hat mir sehr geholfen, Danke!
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Fragen zu vector<Klasse*>

Beitrag von Schrompf »

nerem hat geschrieben: Aber das lag dann also daran, dass ich die Adresse des Zeigers auf den Zeiger ausgegeben habe?!
Exakt.
Hat mir sehr geholfen, Danke!
Sehr gern. Viel Spaß, viel Erfolg.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2353
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Fragen zu vector<Klasse*>

Beitrag von Jonathan »

nerem hat geschrieben: nach jahrelanger Abwesenheit, was Programmierung anbelangt, versuche ich zur Zeit wieder etwas ins Programmieren zu kommen, alte Kenntnisse aufzufrischen und neue Kentnisse zu erlangen. Und prompt stellt man sich die eine oder andere Frage.
Lies am besten das hier:
https://github.com/isocpp/CppCoreGuidel ... S-resource

Smartpointer machen dir in C++ das Leben (bzw. Speicherverwaltung) so viel einfacher, das man sie unbedingt und konsequent benutzen sollte. Es erfordert etwas Einarbeitung, sorgt aber am ende für stabileren und besser strukturierten Code.
(Der Rest der CoreGuidelines ist natürlich auch wärmstens zu empfehlen).
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
nerem
Beiträge: 15
Registriert: 15.03.2012, 22:18

Re: Fragen zu vector<Klasse*>

Beitrag von nerem »

Super Sache, dankeschön. Sehr hilfreiches Dokument, aber das erschlägt einen ja nahezu ;-) Kommt auf alle Fälle zu den Lesezeichen.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2353
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Fragen zu vector<Klasse*>

Beitrag von Jonathan »

nerem hat geschrieben:Super Sache, dankeschön. Sehr hilfreiches Dokument, aber das erschlägt einen ja nahezu ;-) Kommt auf alle Fälle zu den Lesezeichen.
Jup, es ist nicht für Anfänger gedacht. Es ist eher für Menschen, die alles über C++ wissen, was es zu wissen gibt und es jetzt nur noch richtig anwenden wollen. D.h. wer die Regeln alle befolgt ist im Allgemeinen echt richtig gut ausgerüstet (bis dass die neuen Sprachfeatures kommen...)
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
scheichs
Establishment
Beiträge: 845
Registriert: 28.07.2010, 20:18

Re: Fragen zu vector<Klasse*>

Beitrag von scheichs »

nerem hat geschrieben: Einrückungen verwende ich, scheint hier beim rüberkopieren verloren gegangen zu sein.
Hatte auch das "Problem", du musst beim code-Tag noch =cpp dazu schreiben, also

Code: Alles auswählen

[code=cpp]
[/code]
nerem
Beiträge: 15
Registriert: 15.03.2012, 22:18

Re: Fragen zu vector<Klasse*>

Beitrag von nerem »

Hehe, alles klar, Danke! Ich versuche es mir zu merken :)
Antworten