Klasse Zugriff auf Objekt

Julia84

Grünschnabel
Hallo,


Ich habe eine Klasse Schlüssel, welche mir einen zusammengesetzten Schlüssel erzeugt. Diese Schlüssel möchte ich gern in einer 2. Klasse Schlüsselmenge abspeichern. Meine Frage ist, wie kann ich vergleichen, ob der von mir erzeugte Schlüssel in der Schlüsselmenge schon ist:

Klasse Schlüssel:

class Key
{
private:
string S1;
string S2;
int Menge;

public:
Key(string sS1,string sS2,int mMenge);
~Key(void);
string getstringS1(){return S1;}
string getstringS2(){return S2;}
int getMenge(){return Menge;}

};

Klasse Schlüsselmenge:

bool KeySet::existiertKey(string k_S1, string k_S2, int mMenge)
{

Key *Temp=new Key(k_S1, k_S2, mMenge);


set <Key> :: iterator itr;
itr=m_KeySet.find(*Temp);

if (itr==m_KeySet.end())
{
Key *Schlüssel=new Key(k_S1,k_S2,mMenge);

m_KeySet.insert(*Schlüssel);
return true;
}

return false;
}


leider meldet er mir einen Fehler... Kann mir hierbei wer helfen? :(

Viele Grüße

Julia
 
Hallo Julia.

Bitte verwende für deinen Code die entsprchenden Code-Tags ([code=cpp] ... [/code] für C++ Code usw. Danke.
Klasse Schlüssel:
C++:
class Key
{
private:
	string S1;
	string S2;
	int Menge;

public:
	Key(string sS1,string sS2,int mMenge);
	~Key(void);
	string getstringS1(){return S1;}
	string getstringS2(){return S2;}
	int getMenge(){return Menge;}
	
};
Du kopierst die Argumente unnötigerweise bei jedem Aufruf und getter-Methoden sollten const sein:
C++:
class Key
{
private:
	string S1;
	string S2;
	int Menge;

public:
	Key(const string& sS1, const string& sS2,int mMenge);
	~Key(void);
	string getstringS1() const {return S1;}
	string getstringS2() const {return S2;}
	int getMenge() const {return Menge;}	
};
Klasse Schlüsselmenge: ...
Du verwaltest Zeiger in deiner Menge. Wenn du nun ein neues Objekt anlegst, bekommt das eine eindeutige Adresse zugewiesen, d.h. dein temp. Objekt wird niemals schon in der Menge enthalten sein (da nur die Adressen verglichen werden).

Du könntest eine Komparator-Funktion schreiben um zu definieren wie Keys verglichen werden können und bei der Erzeugung des std::set zuweisen:
C++:
bool key_compare(const Key* k1, const Key* k2) {
  if (k1->getstringS1() < k2->getstringS2()) return true;
  else if (...)
}

std::set<Key*, key_compare> m_KeySet;

leider meldet er mir einen Fehler...
Welchen?

Gruß

PS: Gibt es eigentlich einen bestimmten Grund, warum du Zeiger in der Menge verwalten willst und deine Objekte nicht direkt in die Menge speicherst?
 
Zuletzt bearbeitet:
Sorry, ich wusste nicht wie man das formatiert...

Mein Hauptproblem ist das ich vorher mit Java gearbeitet habe und nun versuche auf C++ umzusteigen und Zeiger gibt es nicht direkt in Java, deswegen kann ich das noch nicht so gut... und ich dachte mit

C++:
Key *Schlüssel=new Key(k_S1,k_S2,mMenge);

m_KeySet.insert(*Schlüssel);

mit dem *Schlüssel greif ich auf den Wert sozusagen zu...

und ich wollte sozusagen die Schlüsselkombination aus beiden vergleichen mit einer anderen Schlüsselkombination und da bin ich mir eben nicht sicher, wie ich dies anstelle...

und danke für die Verbesserungen :)
 
und ich dachte mit

C++:
Key *Schlüssel=new Key(k_S1,k_S2,mMenge);

m_KeySet.insert(*Schlüssel);
mit dem *Schlüssel greif ich auf den Wert sozusagen zu...
Richtig, da hab ich nicht richtig gekuckt. Du willst ja gar keine Zeiger in dem Set verwalten.

Da aber ein std::set die Elemente sortiert vorhält muß eine Halbordnung auf den Elementen definiert sein. D.h. du mußt für deine Key Klasse den operator< definieren:
C++:
bool operator<(const Key& k1, const Key& k2) {+
  // here true zurückgeben wenn k1 kleiner ist als k2, sonst false.
}

Außerdem müssen Objekte die man in STL Kontainer speichern möchte "default-constructable" sein. D.h. du mußt einen Default-Konstruktor definieren.

Außerdem ist es in C++ unüblich für alles ein Objekt auf dem Heap anzufordern (denn das mußt du auch wieder wegräumen, was du anscheinend vergessen hast => Speicherleck). Es reicht ein temp. Objekt aus:
C++:
set <Key> :: iterator itr;
itr=m_KeySet.find(Key("x", "y", 2));

Du hast immer noch nicht gesagt welcher Fehler auftritt!?

Gruß
 
Ach so den Fehler genau kann ich dir nicht mehr sagen, da ich ja gerade von dir gelernt habe, dass ich das total falsch mache und gerade versuche es umzuschreiben... Es war irgendwas von wegen ich versuch int in string zu speichern...

Mal ne ganz dumme Frage, warum muss ich zustäzlich den Operator < definieren? Ich wollte doch nur in meiner Klasse die Schlüssel verwalten... also schaun, ob ich schon eine Schlüsselkombination habe oder nicht und wenn nicht, soll er das dann in die Klasse Keyset hinzufügen...

Irgendwie bin ich jetzt total verwirrt :(
 
Mal ne ganz dumme Frage, warum muss ich zustäzlich den Operator < definieren? Ich wollte doch nur in meiner Klasse die Schlüssel verwalten...
Das habe ich doch gerade erklärt. :confused:

In einem std::set werden die Element sortiert gespeichert - es muss eine Halbordnung auf den Elementen definiert sein, damit man sie sortieren kann.

Standardmäßig wird versucht Objekte anhand des operator< zu sortieren.
Und also schaun, ob ich schon eine Schlüsselkombination habe oder nicht und wenn nicht, soll er das dann in die Klasse Keyset hinzufügen..
Das wird automatisch auch vom operator< mit abgedeckt:

Code:
!(a < b) && !(b < a) <=> a == b
In Worten: wenn a nicht kleiner als b ist und b auch nicht kleiner als a, genau dann müssen a und b gleich sein.

\edit: ein std::set ist im Übrigen ein eindeutiger assoziativer Kontainer, d.h. wenn du versuchst ein Element einzufügen, was bereits drin ist, ändert das nichts am Kontainer. Du brauchst also vorher nicht kontrollieren ob bereits ein solches Element drin ist, da es sowieso nicht doppelt eingefügt wird.

Gruß
 
Zuletzt bearbeitet:
Oh man wahrscheinlich steh ich voll auf dem Schlauch, kann mich da bitte mal wer runterschubsen...

Also ich machs mal am Beispiel... meine erste Keykombination besteht aus "hallo" und "du" mit dem Wert 2 , so dann rechnet mein Programm noch ne Weile und dann später will er wieder eine Schlüsselkombination aus "Hallo" und "du " abspeichern und soll wissen, hey.. diese Kombination gibt es shcon, deswegen kann ichs nicht nochmal in die Klasse KeySet einfügen...

Wie kann ich denn da vergleichen ob "Hallo du" < "hallo du" ist.... och man das frustriert mich.. ich raffs einfach nicht...

ich hab mal versucht so anzupassen und nu meckert der das ich key nicht in const & key konvertieren kann... heute ist echt nicht mein Tag....

C++:
bool KeySet::existiertKey(string k_S1,string k_S2, int mMenge)
{
	
	set <Key*> :: iterator itr;
	itr=m_KeySet.find(Key(k_S1, k_S2, mMenge));
	
	if (itr==m_KeySet.end())
	{
				Key *Schlüssel=new Key(k_S1,k_S2,mMenge);
				m_KeySet.insert(Schlüssel);
				return true;
	}

	return false;
}

	Key(const string& sS1, const string& sS2,int mMenge);
	~Key(void);
	string getstringS1() const {return S1;}
	string getstringS2() const {return S2;}
	int getMenge() const {return Menge;}
 
Also ich machs mal am Beispiel... meine erste Keykombination besteht aus "hallo" und "du" mit dem Wert 2 , so dann rechnet mein Programm noch ne Weile und dann später will er wieder eine Schlüsselkombination aus "Hallo" und "du " abspeichern und soll wissen, hey.. diese Kombination gibt es shcon, deswegen kann ichs nicht nochmal in die Klasse KeySet einfügen...

Wie kann ich denn da vergleichen ob "Hallo du" < "hallo du" ist.... och man das frustriert mich.. ich raffs einfach nicht...
Für std::string ist bereits ein operator< definiert.
ich hab mal versucht so anzupassen und nu meckert der das ich key nicht in const & key konvertieren kann...
Bitte gib die genaue Fehlermeldung an und sag dazu welche Zeile dort gemeint ist.

Wie sieht denn jetzt dein operator< jetzt aus?

C++:
bool KeySet::existiertKey(string k_S1,string k_S2, int mMenge)
{
	
	set <Key*> :: iterator itr;
	itr=m_KeySet.find(Key(k_S1, k_S2, mMenge));
	
	if (itr==m_KeySet.end())
	{
				Key *Schlüssel=new Key(k_S1,k_S2,mMenge);
				m_KeySet.insert(Schlüssel);
				return true;
	}

	return false;
}
So wie es aussieht, willst du ja ein Objekt einfügen wenn es noch nicht drin ist, und du möchtest hinterher wissen ob schon eins drin war. Das ginge so:
C++:
bool KeySet::insert(const string& s1, const string& s2, int menge) {
  return m_KeySet.insert(Key(s1, s2, menge)).second;
}
Gruß
 
Für std::string ist bereits ein operator< definiert.

Bitte gib die genaue Fehlermeldung an und sag dazu welche Zeile dort gemeint ist.

Wie sieht denn jetzt dein operator< jetzt aus?


So wie es aussieht, willst du ja ein Objekt einfügen wenn es noch nicht drin ist, und du möchtest hinterher wissen ob schon eins drin war. Das ginge so:

Gruß

also das ist in der find-Zeile:

error C2664: 'std::_Tree<_Traits>::iterator std::_Tree<_Traits>::find(const std::_Tree<_Traits>::key_type & )': Konvertierung des Parameters 1 von 'Key' in 'const std::_Tree<_Traits>::key_type & ' nicht möglich
with
[
_Traits=std::_Tset_traits<Key *,std::less<Key *>,std::allocator<Key *>,false>
]
and
[
_Traits=std::_Tset_traits<Key *,std::less<Key *>,std::allocator<Key *>,false>
]


mein <Operator ist auch falsch weil ich zugegebener Maßen, dass nicht richtig verstehe... er sagt mir dass da zuviele Elemente bei < sind
C++:
bool operator<(const Key& k1, const Key& k2) {
  if( k1<k2)
return true;

return false;
}
 
Zuletzt bearbeitet:
also das ist in der find-Zeile:

error C2664: 'std::_Tree<_Traits>::iterator std::_Tree<_Traits>::find(const std::_Tree<_Traits>::key_type & )': Konvertierung des Parameters 1 von 'Key' in 'const std::_Tree<_Traits>::key_type & ' nicht möglich
with
[
_Traits=std::_Tset_traits<Key *,std::less<Key *>,std::allocator<Key *>,false>
]
and
[
_Traits=std::_Tset_traits<Key *,std::less<Key *>,std::allocator<Key *>,false>
]
Jetzt hast du plötzlich doch ein std::set<Key*>, also eine Menge von Zeigern auf Key. Warum das denn?
mein <Operator ist auch falsch weil ich zugegebener Maßen, dass nicht richtig verstehe... er sagt mir dass da zuviele Elemente bei < sind
Bitte poste die Fehlermeldung. Der Compiler hat mit Sicherheit nicht "zuviele Elemente bei <" ausgegeben, oder?!
C++:
bool operator<(const Key& k1, const Key& k2) {
  if( k1<k2)
return true;

return false;
}
So kann es natürlich nicht funktioneren. Du sagst hier ja, k1 ist kleiner als k2 wenn k1 kleiner als k2 ist. :confused:

Du mußt den operator< anhand der Attribute der Klasse definieren. Eine Möglichkeit wäre z.B.:
C++:
bool operator<(const Key& k1, const Key& k2) {
  return 
     k1.getMenge() < k2.getMenge() 
     || (k1.getMenge() == k2.getMenge() 
         && (k1.getstringS1() < k2.getstringS1()
                || (k1.getstringS1() == k2.getstringS1()
                    && k1.getstringS2() < k2.getstringS2())));
}
 
Zurück