(map) Template Klasse vererben
-
Hallo, ich versuche gerade die Template Klasse map abzuleiten. Vorweg sollte ich vielleicht sagen, das Template's für mich Neuland sind.
Ich habe mich durch einige Tuts gelesen und versucht diese nachzubilden. Leider motzt mein Compiler rum und ich hab da noch einige Fragen die ich leider nicht beantwortet bekomme.
#include <map> using namespace std; template <class Key, // map::key_type class Type, // map::mapped_type class Compare = less<Key>, // map::key_compare class Alloc = allocator<pair<const Key, Type> > // map::allocator_type > class CStdMap : public map<Key, Type, Compare, Alloc> { public: CStdMap ( ); virtual ~CStdMap( ); void Add (Key _K, Type _T); };
#include <StdMap.h> template < class Key, class Type, class Compare = less<Key>,class Alloc = allocator<pair<const Key, Type>> CStdMap<Key, Type ,Compare ,Alloc>::CStdMap() : map(Key, Type) { } template < class Key, class Type, class Compare = less<Key>,class Alloc = allocator<pair<const Key, Type>> CStdMap<Key, Type ,Compare ,Alloc>::~CStdMap(void) { } template < class Key, class Type, class Compare = less<Key>,class Alloc = allocator<pair<const Key, Type>> void CStdMap<Key, Type ,Compare ,Alloc>::Add(Key _K, Type _T) { insert(std::make_pair(_K,_T)); }
Soweit lässt sich der Code problemlos Compilern, versuche ich jetzt aber auf die Klasse CStdMap in meiner Anwendung zuzugreifen, indem ich eine Variable für die Klasse erstelle gehn die Probleme los.
typedef CStdMap<int,int> STDMAP; //Klappt noch STDMAP m_Stdmap;//Klappt nicht Compiler motzt (nicht aufgelöstes externes Symbol)
Fehlermeldung schrieb:
error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall CStdMap<int,int,struct std::less<int>,class std::allocator<struct std::pair<int const ,int> > >::CStdMap<int,int,struct std::less<int>,class std::allocator<struct std::pair<int const ,int> > >(void)" (??0?less@H@std@@V?pair@$$CBHH@std@@@2@@@QAE@XZ)" in Funktion ""void __cdecl `dynamic initializer for 'ms''(void)" (??__Ems@@YAXXZ)
error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: virtual __thiscall CStdMap<int,int,struct std::less<int>,class std::allocator<struct std::pair<int const ,int> > >::~CStdMap<int,int,struct std::less<int>,class std::allocator<struct std::pair<int const ,int> > >(void)" (??1?less@H@std@@V?pair@$$CBHH@std@@@2@@@UAE@XZ)" in Funktion ""void __cdecl `dynamic atexit destructor for 'ms''(void)" (??__Fms@@YAXXZ)
fatal error LNK1120: 2 nicht aufgelöste externe Verweise.
wenn ich jetzt versuche den Prototypen meiner Template Klasse ein typedef voranzustellen klappt es wieder! aber bei der Klasse map muss man das ja auch nicht machen. warum geht das bei mir nicht.
typedef CStdMap<int,int> STDMAP; //Klappt noch typedef STDMAP m_Stdmap;//Klappt so lässt sich jetzt Compilern
Versuche ich jetzt aber über die Klassen-Variable auf eine Funktion zuzugreifen, egal ob die Funktion in CStdMap oder der Basis-Klasse map ist, motzt wieder der Compiler.
m_Stdmap.Add(0,1);//Compiler motzt m_Stdmap.insert(std::make_pair(0,1));//Compiler motzt
Fehlermeldung schrieb:
error C2143: Syntaxfehler: Es fehlt ';' vor '.'
Warum kann ich nicht auf die Funktionen zugreifen?
-
Der komplette Code von Templates muß im Header vorliegen.
Aber welchen Sinn macht es von den Standard-Containerklassen abzuleiten? Diese sind nicht polymorph (haben keinen virtuellen Destruktor)!
-
Aber welchen Sinn macht es von den Standard-Containerklassen abzuleiten?
ich möchte gern ne klasse wie CArray erstellen.
Der komplette Code von Templates muß im Header vorliegen.
die Funktion Add liegt doch aber im Code vor!? oder nicht...
-
LowFly schrieb:
Aber welchen Sinn macht es von den Standard-Containerklassen abzuleiten?
ich möchte gern ne klasse wie CArray erstellen.
Der Grund für dein Vorhaben ist also, dass du dein Vorhaben umsetzen möchtest.
Definier doch mal, was "ne Klasse wie CArray" auszeichnen soll. Dass (public) Vererbung auf jeden Fall ein falsches Mittel sein muss, wurde dir schon erklärt. Was möchtest du erreichen? Eine Schnittstelle wie die von map? Das wäre private Vererbung. Aber höchstwahrscheinlich möchtest du Komposition.
Der komplette Code von Templates muß im Header vorliegen.
die Funktion Add liegt doch aber im Code vor!? oder nicht...
Im Header! Bitte genau lesen.
-
du musst ganz schnell aufhören von STL Containern abzuleiten - das macht man nicht
mach einfach
class CArray { private: map<...> }
Warum: neben der Info von Th69 sollten man so viel wie möglich auf Ableitung verzichten und hat hier auch absoluten keinen Vorteil
du hast sowieso einen andere Schnittstelle - und mit private Ableitung zu arbeiten nur damit nichts von dem Basis-Interface rausdringt ist totaler Quark - höchstens du willst die STL-Schnittstelle zusätzlich anbieten?
-
SeppJ schrieb:
Was möchtest du erreichen? Eine Schnittstelle wie die von map? Das wäre private Vererbung.
Wie ist das gemeint?
Wieso ist private Vererbung == Schnittstelle übernehmen?Die Schnittstelle (=public-krams) von map ist doch gerade nicht mehr public (=Teil der Schnittstelle)?
-
Jockelx schrieb:
SeppJ schrieb:
Was möchtest du erreichen? Eine Schnittstelle wie die von map? Das wäre private Vererbung.
Wie ist das gemeint?
Wieso ist private Vererbung == Schnittstelle übernehmen?Es ist ein bisschen schwer in Worten zu beschreiben, was private-Vererbung genau ausdrückt. Höchstwahrscheinlich ist es nicht das Mittel, dass der TE (oder irgendjemand) sucht, daher bin ich nicht näher darauf eingegangen. Was man bei privater Vererbung machen kann, ist, dass man intern die gesamte Schnittstelle übernimmt und gleichzeitig ausgewählte Teile der geerbten Schnittstelle nach außen hin verfügbar machen kann, ohne jeweils einen Wrapper zu schreiben. Außerdem funktioniert dies auch noch, wenn die Basisklasse, wie hier, keinen virtuellen Destruktor hat. Und es gibt noch ein paar andere Anwendungsszenarien anderer Natur. Letztlich ist es aber eine ähnliche Beziehung wie Komposition, nur dass eben solche Schnittstellenfragestellungen jeweils etwas anders gehandhabt werden. In den meisten Fällen liefert Komposition die besser passenden Antworten auf diese Fragestellungen.
Aber wie schon gesagt, es ist eher unwahrscheinlich, dass der TE irgendetwas davon möchte. Aber bevor er nicht mehr sagt als "ne klasse wie CArray erstellen", kann man ihm leider nicht helfen.
-
Hallo Sepp,
SeppJ schrieb:
Was man bei privater Vererbung machen kann, ist, dass man intern die gesamte Schnittstelle übernimmt und gleichzeitig ausgewählte Teile der geerbten Schnittstelle nach außen hin verfügbar machen kann, ohne jeweils einen Wrapper zu schreiben.
Und das nach aussen verfügbar machen, meinst du so:
class A : private std::vector<int> { public: size_t size() { return std::vector<int>::size(); } }
Oder geht das schlauer/besser?
Edit:
Ach ja, mit using geht das.Danke.
-
Nein, eben gerade nicht so. Einer der Gründe für private-Vererbung ist ja gerade, dass so etwas dann schön einfach geht:
class A : private std::vector<int> { public: using std::vector<int>::size; }
edit: Zu langsam...
-
Seppel schrieb:
Aber bevor er nicht mehr sagt als "ne klasse wie CArray erstellen", kann man ihm leider nicht helfen.
naja ich weis nicht was es da noch zu erklären gäbe... ich könnte höchstens versuchen mich etwas gepflegter auszudrücken...
Ich würde mir gerne eine Klasse erstellen, die der Klasse CArray von MFC in ihrer Arbeits-, Funktionsweise sowie Funktionsbezeichnung ähnelt.Seppel schrieb:
Im Header! Bitte genau lesen.
hab ich, ich hab es nur anders verstanden als es gemeint war. Und bevor nochmal Fragen kommen. Ich dachte dass der komplette headercode der Klasse map in meiner header datei vorliegen muss...
Th69 schrieb:
Der komplette Code von Templates muß im Header vorliegen
Danke das wars, auch wenn ich's nicht gleich kapiert hab was du damit gemeint hast. In den Tuts die ich gelesen habe ist es auch genau so beschrieben, ich habs halt einfach falsch verstanden.
@Gast3
danke versuch zu beherzigen und umzusetzen...
-
LowFly schrieb:
CArray von MFC
Und du hältst das nicht für einen gewaltigen Unterschied zu
CArray
?
std::vector dürfte wohl das Gegenstück sein. Willst du jetzt exakt die gleichen Methodennamen?
Ich würde mir die MFC höchstens als abschreckendes Beispiel ansehen ...
-
LowFly schrieb:
naja ich weis nicht was es da noch zu erklären gäbe... [...]
Ich würde mir gerne eine Klasse erstellen, die der Klasse CArray von MFC [...] ähnelt.Das ist doch schon eine deutliche Erklärung (Hervorhebung von mir). Woher sollen wir wissen, dass du MFC nachbauen willst? Es hätte auch sein können, das du std::array nachbauen willst oder irgendein Array aus irgendeiner anderen Bibliothek oder einfach "irgendwas mit Arrays" meinst.
Edit: manni66 war schneller. Krass, das wo sind die 10 Minuten Zeitdifferenz her?! Habe ich so lange zum schreiben gebraucht oder noch noch was anderes zwichendurch gemacht?