Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   

Die mobilen Seiten von c++.de:
http://m.c-plusplus.de
Infos hier [BETA]

  
c++.de :: C++ (auch C++0x und C++11) ::  Vector von Basisklasse und Aufruf virtueller Funktionen     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
jule86
Unregistrierter




Beitrag jule86 Unregistrierter 20:31:57 29.06.2012   Titel:   Vector von Basisklasse und Aufruf virtueller Funktionen            Zitieren

Hallo liebes Forum! Ich komme aus der Java Welt und stolpere über ein wahrscheinlich triviales C++ Problem.

Ich habe eine Instanz von vector<Fahrzeug> und möchte über alle Fahrzeuge iterieren. Die Klasse Fahrzeug hat eine virtual print() Methode, die in den jeweiligen Klassen überschrieben ist und den Typ ausgibt, ob es eine Subklasse von Auto, LKW oder Motorrad ist.

Nun mein Problem liegt in folgendem Code:
C++:
for(vector<Fahrzeug>::iterator i = v.begin(); i != v.end(); ++i) {
    (*i).print();
}


In Java würde dieser Code jeweils den entsprechenden Typ (also z. B. Auto) ausgeben, in meinem Beispiel aber immer Fahrzeug. Eine google Recherche brachte den Begriff Slicing hervor, allerdings verstehe ich nicht, wie ich dieses Problem lösen kann?! :(
Kellerautomat
Mitglied

Benutzerprofil
Anmeldungsdatum: 03.06.2012
Beiträge: 904
Beitrag Kellerautomat Mitglied 20:37:22 29.06.2012   Titel:              Zitieren

Willkommen im Forum!

Ja, dein ergoogelter Begriff ist richtig. Da C++ keine Indirektionen aufzwingt, wird hier der Teil der abgeleiteten Klasse einfach abgeschnitten. Indem du jetzt selbst Zeiger verwendest, kannst du das Problem lösen:
C++:
vector<Fahrzeug*>

Bzw noch besser:
C++:
vector<unique_ptr<Fahrzeug>>

Das Problem bei Zeigern im Vector ist nämlich dass der Vector die Objekte hinter den Zeigern nicht automatisch mitlöscht. Dazu dient unique_ptr. Genaueres schlägst du am besten nach. :)

Grüße,
Der Kellerautomat
Sone
Mitglied

Benutzerprofil
Anmeldungsdatum: 29.05.2012
Beiträge: 3187
Beitrag Sone Mitglied 20:37:58 29.06.2012   Titel:              Zitieren

Du brauchst einen Basisklassenzeiger. Also

C++:
std::vector<Fahrzeug*> v;
v.push_back( new Auto("Golf GTI Ich hab keine Ahnung von Autos") );


Dann wird die virtuelle Methode, wenn sie in Auto überschrieben wurde, auch in Auto aufgerufen (also die, die in Auto definiert wurde und nicht die in der Basisklasse).

Hol dir ein gutes Buch, Thread gibts im Forum.

Versuch am besten aus Fahrzeug eine abstrakte Basisklasse zu machen.

_________________
You want to do X, and you think Y is the best way of doing so. Instead of asking about X, you ask about Y. | Wenn man was zum Lachen braucht: Why C++ Sucks


Zuletzt bearbeitet von Sone am 20:39:21 29.06.2012, insgesamt 1-mal bearbeitet
Sone
Mitglied

Benutzerprofil
Anmeldungsdatum: 29.05.2012
Beiträge: 3187
Beitrag Sone Mitglied 20:47:11 29.06.2012   Titel:              Zitieren

Kellerautomat schrieb:

Das Problem bei Zeigern im Vector ist nämlich dass der Vector die Objekte hinter den Zeigern nicht automatisch mitlöscht. Dazu dient unique_ptr. Genaueres schlägst du am besten nach. :)


Dann kann er gleich boost::ptr_vector nehmen :)

_________________
You want to do X, and you think Y is the best way of doing so. Instead of asking about X, you ask about Y. | Wenn man was zum Lachen braucht: Why C++ Sucks
Unregistrierter





Beitrag Unregistrierter 21:10:32 29.06.2012   Titel:   Re: Vector von Basisklasse und Aufruf virtueller Funktionen            Zitieren

jule86 schrieb:
Ich komme aus der Java Welt und stolpere über ein wahrscheinlich triviales C++ Problem.
C++:
for(vector<Fahrzeug>::iterator i = v.begin(); i != v.end(); ++i) {
    (*i).print();
}
Da muss man dich loben. Die meisten, die von Java kommen, halten großen Abstand von der STL und handeln sich dadurch nur Probleme ein.


Es wird immer eine Kopie des Objekts in den vector eingefügt.
C++:
Auto a;
Fahrzeug f = a;
Bei der Kopie f = a werden natürlich nur Fahrzeug-Informationen, die a hat, kopiert (alles andere wäre auch sehr unlogisch). Damit ist dir hoffentlich auch klar, warum immer die print-Methode von Fahrzeug aufgerufen wird.
Lösung: Referenzen oder Zeiger verwenden. Referenzen kann ein Container nicht aufnehmen, damit bleiben dir nur noch die Zeiger. Beim Einfügen in den vector wird dann der Zeiger kopiert. Das eigentliche Objekt bekommt von alldem nichts mit. Da deine Klassen polymorph sind, wird dann je nach Datentyp des Pointees die entsprechende Methode aufgerufen, genauso, wie du es dir erwartet hast.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <iterator>
#include <vector>
using namespace std;
 
 
class Fahrzeug
{
    public:
        virtual void print() = 0;
};
 
 
class Auto : public Fahrzeug
{
    public:
        virtual void print()
        {
            cout << '\n' << "Auto";
        }
};
class LKW : public Fahrzeug
{
    public:
        virtual void print()
        {
            cout << '\n' << "LKW";
        }
};
class Motorrad : public Fahrzeug
{
    public:
        virtual void print()
        {
            cout << '\n' << "Motorrad";
        }
};
 
 
int main()
{
    vector<Fahrzeug*> fahrzeuge;
 
    Auto a;
    LKW l;
    Motorrad m;
 
    fahrzeuge.push_back(&a);
    fahrzeuge.push_back(&l);
    fahrzeuge.push_back(&m);
 
    for(vector<Fahrzeug*>::iterator it=fahrzeuge.begin(); it!=fahrzeuge.end(); ++it)
    {
        (*it)->print();
    }
 
    return 0;
}


Siehe auch: http://stackoverflow.com/ ....... ss-and-collections-vector
TyRoXx
Mitglied

Benutzerprofil
Anmeldungsdatum: 30.06.2009
Beiträge: 1034
Beitrag TyRoXx Mitglied 12:50:35 30.06.2012   Titel:   Re: Vector von Basisklasse und Aufruf virtueller Funktionen            Zitieren

Gugelmoser schrieb:

C++:
class Fahrzeug
{
    public:
        virtual void print() = 0;
};

Da fehlt ein virtueller Destruktor, falls der Vektor die Objekte besitzen und korrekt zerstören soll.
C++:
class Fahrzeug
{
    public:
        virtual ~Fahrzeug() {}
        virtual void print() = 0;
};

_________________
.. aber dann wäre C++ uneinheitlich und nicht mehr so anfängergerecht.
theta
Mitglied

Benutzerprofil
Anmeldungsdatum: 26.09.2008
Beiträge: 4079
Beitrag theta Mitglied 12:59:09 30.06.2012   Titel:              Zitieren

Zitat:
Da fehlt ein virtueller Destruktor, falls der Vektor die Objekte besitzen und korrekt zerstören soll.

Und falls nicht, tut man gut daran den Destruktor non-virtual protected zu machen.
c++.de :: C++ (auch C++0x und C++11) ::  Vector von Basisklasse und Aufruf virtueller Funktionen   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.