Copy Constructor und operator= ???
-
Hallo

seit einiger Zeit beschaeftige ich mich wieder mal mit C++ und Gtkmm.
Dabei hab ich bei der Implementierung von Copy Constructoren und den Zuweisungsoperator = .Folgender Code:
#ifndef ENTRY_H #define ENTRY_H #include <iostream> #include <list> #include <map> #include <string> #include <glibmm/ustring.h> class Entry : public std::map<guint, Glib::ustring> { public: Entry(); virtual ~Entry(); Entry& operator=(const Entry& entry); protected: private: }; class List : public std::list<Entry> { public: List(); List(const List& list); virtual ~List(); protected: private: }; #endifDazu die kritischen Implementierungen:
Entry& Entry::operator=(const Entry& entry) { /* if (this != &entry) { for (Entry::iterator iter = entry.begin(); iter != entry.end(); iter++) { gint first = (*iter).first; Glib::ustring second = (*iter).second; (*this)[first] = second; } } */ Entry::iterator iter = entry.begin(); return *this; } List::List(const List& list) { List::iterator iter = list.begin(); /* for (List::iterator iter = list.begin(); iter != list.end(); iter++) ; */ }Der Fehler lautet:
list.cc: In member function 'Entry& Entry::operator=(const Entry&)': list.cc:28: error: conversion from 'std::_Rb_tree_const_iterator<std::pair<const unsigned int, Glib::ustring> >' to non-scalar type 'std::_Rb_tree_iterator<std::pair<const unsigned int, Glib::ustring> >' requested list.cc: In copy constructor 'List::List(const List&)': list.cc:40: error: conversion from 'std::_List_const_iterator<Entry>' to non-scalar type 'std::_List_iterator<Entry>' requestedEs scheint mit den Iteratoren bezueglich der Map und List zu sein, aber wieso?
Warum aber?
-
Erstens sollte man von den STL-Container-Typen nicht ableiten und zweitens hast du ein const-Problem. Der Rückgabetyp der begin() Funnktion ist in diesem Fall kein iterator, sondern ein const_iterator.
-
Ja, der erwartet einen const_iterator statt eines iterator.
StattEntry::iterator iter = entry.begin();dies
Entry::const_iterator iter = entry.begin();Greetz
-
Mach aus deinem gesammten code folgendes:
typedef std::map<guint, Glib::ustring> Entry; typedef std::list<Entry> List;oder hat das in deinem Fall irgendwelche Nachteile?
-
Helium schrieb:
Mach aus deinem gesammten code folgendes:
typedef std::map<guint, Glib::ustring> Entry; typedef std::list<Entry> List;oder hat das in deinem Fall irgendwelche Nachteile?
Naja, das wuerde mit den angegebenen Kode ja gehen, aber ich hab mein Problem nur auf das Notwendige reduziert und das dann gepostet.
Aber ich werde mit das mit dem const_iterator anschaun.
Aber wieso sollte man nicht von std container-typen nicht ableiten?
-
Die Destruktoren der STL-Container sind nicht virtuell. Folglich ist zumindest public-Ableiten gefährlich (geht sofort schief, wenn du ein Objekt einer abgeleiteten Klasse über einen Basisklassenzeiger löschst).
-
Gibt es denn alternativen zu Map und List?
-
Zu deinen Klassen Map und List?
Ja, bestimmt.Falls du std::map und std::list mit virtuellem Destruktor meinst, so lautet die Antwort nein. Und das ist gut so. Von einem Container abzuleiten deutet IMHO im Allgeminen auf einen fundamentalen Designfehler hin.
-
Z2 schrieb:
Zu deinen Klassen Map und List?
Ja, bestimmt.Falls du std::map und std::list mit virtuellem Destruktor meinst, so lautet die Antwort nein. Und das ist gut so. Von einem Container abzuleiten deutet IMHO im Allgeminen auf einen fundamentalen Designfehler hin.
Designfehler - selbst nach 3 Jahren Studium hab ich davon noch nichts gehoert, aber vielleicht ist das ja in Java etwas anderes.
Sollte ich mir etwa die Funktionalitaet von List und Map selbst nachprogrammieren?
Ich koennte natuerlich auch die boost-bibliothek verwenden, aber das moechte ich nicht unbedingt ...
-
Java != C++
Mit den OOP-Methoden aus Java kommst du in C++ gewöhnlich nicht sehr weit. Du sollst die Container natürlich nicht noch mal neu implementieren. Ich nehme an, der Unterschied zwischen einer ist-ein und einer hat-ein Relation ist dir wohl bekannt, oder?
-
Natuerlich, und die Klasse List soll auch eine Liste sein, die Liste soll als Attribut eine Map besitzen.
in der Map sollen die IDs zu bestimmten eintraegen stehen, die Werte in der Klasse Entry (Map) spezifizieren.Wie wuerdest du das denn planen, List als List mit attribut Map oder List als Map mit attribut list? So oder so, List als std::list wuerde mir vom Designstatus jedenfalls besser gefallen.
-
Bin mir jetzt nicht sicher, ob ich dich richtig verstanden habe. Deine Klasse besteht aus einer Liste und hat zusätzlich eine Map? In dem Fall sollte die Klasse sowohl die Liste als auch die Map als Attribut haben.
-
Natuerlich waere das auch ne moeglichkeit, aber die liste soll durch die map nur spezialisiert und erweitert werden.
Dazu brauche ich keine Klasse die zwei Attribute verwaltet.
Seh ich das wirklich so falsch?
-
IMHO, ja! Deine "Liste" ist eben keine Liste mehr. Eine Liste hat nämlich keine Map. Auch eine spezialisierte Liste hat keine Map.
Zu vererben nur weil man die Funktionalitäten der Oberklasse übernehmen will, ist normalerweise eine falsche Entscheidung (und wenn es noch so bequem ist).