Fragen zu vector<Klasse*>

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.

Fragen zu vector<Klasse*>

Beitragvon nerem » 28.06.2017, 10:30

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: Ansicht erweitern :: 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: Ansicht erweitern :: 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: Ansicht erweitern :: 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
nerem
 
Beiträge: 9
Registriert: 15.03.2012, 23:18

Re: Fragen zu vector<Klasse*>

Beitragvon Schrompf » 28.06.2017, 11:02

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 :-)
Häuptling von Dreamworlds. Baut an was Neuem. Hilft nebenbei nur höchst selten an der Open Asset Import Library mit.
Benutzeravatar
Schrompf
Thomas Ziegenhagen
Moderator
 
Beiträge: 3580
Registriert: 26.02.2009, 00:44
Wohnort: Dresden
Benutzertext: Lernt nur selten dazu

Re: Fragen zu vector<Klasse*>

Beitragvon nerem » 28.06.2017, 11:25

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!
nerem
 
Beiträge: 9
Registriert: 15.03.2012, 23:18

Re: Fragen zu vector<Klasse*>

Beitragvon Schrompf » 28.06.2017, 12:18

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.
Häuptling von Dreamworlds. Baut an was Neuem. Hilft nebenbei nur höchst selten an der Open Asset Import Library mit.
Benutzeravatar
Schrompf
Thomas Ziegenhagen
Moderator
 
Beiträge: 3580
Registriert: 26.02.2009, 00:44
Wohnort: Dresden
Benutzertext: Lernt nur selten dazu

Re: Fragen zu vector<Klasse*>

Beitragvon Jonathan » 28.06.2017, 15:26

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!
Benutzeravatar
Jonathan
 
Beiträge: 1129
Registriert: 04.08.2004, 20:06

Re: Fragen zu vector<Klasse*>

Beitragvon nerem » 28.06.2017, 17:39

Super Sache, dankeschön. Sehr hilfreiches Dokument, aber das erschlägt einen ja nahezu ;-) Kommt auf alle Fälle zu den Lesezeichen.
nerem
 
Beiträge: 9
Registriert: 15.03.2012, 23:18

Re: Fragen zu vector<Klasse*>

Beitragvon Jonathan » 29.06.2017, 14:34

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!
Benutzeravatar
Jonathan
 
Beiträge: 1129
Registriert: 04.08.2004, 20:06

Re: Fragen zu vector<Klasse*>

Beitragvon scheichs » 05.07.2017, 15:00

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: Ansicht erweitern :: Alles auswählen
[code=cpp][/code]
scheichs
 
Beiträge: 195
Registriert: 28.07.2010, 20:18

Re: Fragen zu vector<Klasse*>

Beitragvon nerem » 06.07.2017, 08:50

Hehe, alles klar, Danke! Ich versuche es mir zu merken :)
nerem
 
Beiträge: 9
Registriert: 15.03.2012, 23:18


Zurück zu Programmiersprachen, Quelltext und Bibliotheken

Wer ist online?

Mitglieder in diesem Forum: Aharabada, Bing [Bot] und 2 Gäste