Überladen des += Operators
- cloidnerux
- Moderator
- Beiträge: 3125
- Registriert: Fr Sep 26, 2008 4:37 pm
- Wohnort: Ram (Gibts wirklich)
Überladen des += Operators
Also, ich will den += Operator in C++ überladen.
Nur verstehe ich nciht ganz wie das Funktioniert
Wie wird der Aufgerufen und was soll er zurückgeben?
Google schweigt sich Tot darüber.
MfG cloidnerux
Nur verstehe ich nciht ganz wie das Funktioniert
Wie wird der Aufgerufen und was soll er zurückgeben?
Google schweigt sich Tot darüber.
MfG cloidnerux
Redundanz macht wiederholen unnötig.
quod erat expectandum
quod erat expectandum
- fat-lobyte
- Beiträge: 1398
- Registriert: Sa Jul 05, 2008 12:23 pm
- Wohnort: ::1
- Kontaktdaten:
Re: Überladen des += Operators
Alle x= operatoren können nur als Memberfunktionen einer Klasse überladen werden. Du musst eine Klasse haben, für das ein += sinnvoll ist.
Die Syntax sieht so aus:
Ein kleines Beispiel
Und so kann man in C++ für den Preis einer recht "unintuitive" Syntax bei der deklaration eine recht Hübsche und intuitive Syntax bei der verwendung erzeugen.
Wobei man dazusagen muss, dass die Syntax nur auf den ersten blick unintuitiv erscheint. Wenn man drüber nachdenkt merkt man, dass die Syntax doch ziemlich logisch ist.
Edit: übrigens, google schweigt sich nicht tot darüber, such nach "c++ operator overloading" und stell davor die Suche auf Englisch das gibt bessere Ergebnisse. Einer davon ist die C++ FAQ-Lite, eine sehr gute und informative Seite über mögliche Fehlerquellen in c++:
http://www.parashift.com/c++-faq-lite/o ... ading.html
Die Syntax sieht so aus:
Code: Alles auswählen
<Rückgabewert> operator += (<AndererTyp> <anderesObjekt>)
Code: Alles auswählen
#include <iostream>
struct MeineKlasse
{
int val;
// konstruktor, objekt wir mit int initialisiert
MeineKlasse(int _val)
: val(_val)
{}
// ueberlade den += operator
MeineKlasse& operator += (int other)
{ val += other; return *this; }
};
// ueberlade den stream operator fuer ostream, damit wir cout benutzen koennen
std::ostream& operator << (std::ostream& os, const MeineKlasse& k)
{ return os<<k.val; }
int main()
{
MeineKlasse mein_objekt(5);
std::cout<<"mein_objekt ist "<<mein_objekt<<'\n'; // verwende stream operator
// verwende += operator
mein_objekt += 22;
std::cout<<"mein_objekt ist jetzt "<<mein_objekt<<'\n';
return 0;
};
Wobei man dazusagen muss, dass die Syntax nur auf den ersten blick unintuitiv erscheint. Wenn man drüber nachdenkt merkt man, dass die Syntax doch ziemlich logisch ist.
Edit: übrigens, google schweigt sich nicht tot darüber, such nach "c++ operator overloading" und stell davor die Suche auf Englisch das gibt bessere Ergebnisse. Einer davon ist die C++ FAQ-Lite, eine sehr gute und informative Seite über mögliche Fehlerquellen in c++:
http://www.parashift.com/c++-faq-lite/o ... ading.html
Haters gonna hate, potatoes gonna potate.
- cloidnerux
- Moderator
- Beiträge: 3125
- Registriert: Fr Sep 26, 2008 4:37 pm
- Wohnort: Ram (Gibts wirklich)
Re: Überladen des += Operators
Also, der += wird sozusoagen als "=" operator angesehn, der aus einem übergebenen objekt einen wert erzeugt und dem Objekt zuweißt?
//Edit:
Hab hier was gutes dazu gefunden: http://tutorial.schornboeck.net/operato ... ladung.htm
//Edit2:
Mein Compiler meldet mit bei folgendem Aufruf einen Fehler:
Und zwar:
Wieso?
//Edit:
Hab hier was gutes dazu gefunden: http://tutorial.schornboeck.net/operato ... ladung.htm
//Edit2:
Mein Compiler meldet mit bei folgendem Aufruf einen Fehler:
Code: Alles auswählen
static hexstring^ operator +=(hexstring^ a);
Code: Alles auswählen
error C2805: Binärer Operator '+=' hat zu wenig Parameter
Zuletzt geändert von cloidnerux am Sa Apr 25, 2009 6:21 pm, insgesamt 1-mal geändert.
Redundanz macht wiederholen unnötig.
quod erat expectandum
quod erat expectandum
Re: Überladen des += Operators
Auf Xin's Homepage gibts eine schöne Erklärung dazu.
Eine Frage hab ich aber noch dazu:
Mein Wissen über C++ beschränkt sich noch eher auf die Theorie. Deshalb versteh ich nicht, wie man in der Methode auf private-Variablen der übergebenen Referenz zugreifen kann? Ich wüsste da nichts Besseres als set und get Methoden zu schreiben.
Eine Frage hab ich aber noch dazu:
Mein Wissen über C++ beschränkt sich noch eher auf die Theorie. Deshalb versteh ich nicht, wie man in der Methode auf private-Variablen der übergebenen Referenz zugreifen kann? Ich wüsste da nichts Besseres als set und get Methoden zu schreiben.
- fat-lobyte
- Beiträge: 1398
- Registriert: Sa Jul 05, 2008 12:23 pm
- Wohnort: ::1
- Kontaktdaten:
Re: Überladen des += Operators
Nur "logisch". Also gedanklich passiert das. Tatsächlich wird auf das Objekt schlicht und einfach die Funktion mit dem namen "operator +=", und mit einem internen this zeiger (den man nicht sieht) aufgerufen, und damit der interne wert erhöht.cloidnerux hat geschrieben:Also, der += wird sozusoagen als "=" operator angesehn, der aus einem übergebenen objekt einen wert erzeugt und dem Objekt zuweißt?
Soweit ich weiß wird kein temporäres objekt erzeugt.
Also erstmal versteh ich nicht was genau das ^ soll. Zweitens hast du etwas zu wenig kontext angegeben, bitte zeichne ein ungefähres bild von hexstring, und wo es verwendet wird.cloidnerux hat geschrieben://Edit2:
Mein Compiler meldet mit bei folgendem Aufruf einen Fehler:Und zwar:Code: Alles auswählen
static hexstring^ operator +=(hexstring^ a);
Wieso?Code: Alles auswählen
error C2805: Binärer Operator '+=' hat zu wenig Parameter
Tatsächlich hatte ich zuerst die Klasse als "class" definiert und die Membervariable auf private gesetzt. Dafür habe ich aber auch den überladenen stream operator als "friend" einauen müssen, und das wollte ich wegen etwaiger Verwirrungen vermeiden.dani93 hat geschrieben:Deshalb versteh ich nicht, wie man in der Methode auf private-Variablen der übergebenen Referenz zugreifen kann?
Als Struct definiert sind alle variablen automatisch public, es sei denn du führst explicit private oder protected zugriffsbeschränkungen ein.
Oder habe ich deine Frage missverstanden?
Das wäre die Java variante, getters und setters für jede kleine mini-variable. Glücklicherweise kann man in C++ intuitiveren Code schreiben.dani93 hat geschrieben: Ich wüsste da nichts Besseres als set und get Methoden zu schreiben.
Wieso denn das? Eine Sprache rein theoretisch zu lernen bringt nicht viel. Wenn du schon so topmotiviert bist und das ganze theoretisch machst, dann mach doch gleich ein "begleitendes" kleines Projekt dazu. Dabei wendest du immer das neu gelernte an. Ich kann dir zwar versprechen, dass du nur Müllcode fabrizieren wirst für den du dich später schämst (so wars zumindest bei mir), aber wenigstens lernst du einiges dabei.dani93 hat geschrieben: Mein Wissen über C++ beschränkt sich noch eher auf die Theorie.
Haters gonna hate, potatoes gonna potate.
- cloidnerux
- Moderator
- Beiträge: 3125
- Registriert: Fr Sep 26, 2008 4:37 pm
- Wohnort: Ram (Gibts wirklich)
Re: Überladen des += Operators
Unter VC++ gibt es die möglichkeit etwas als eigenschaft zu definieren die eine get funktion hat, die automatisch aufgerufen wird wenn man darauf zugreift.
Aber ich habe auch ncoh eine Frage:
KAnn man den "=" operator so überladen, das er der Classe z.B einen Int wert zuweiß, alos ungefähr so:
Weil bie mir meldet er bei diesen Aufruf keinen fehler, aber wenn cih versuche nun einem Objekt dieser Klasse einen Int wert zuzuweisen meldet er mir immer:
Wieso?
Aber ich habe auch ncoh eine Frage:
KAnn man den "=" operator so überladen, das er der Classe z.B einen Int wert zuweiß, alos ungefähr so:
Code: Alles auswählen
hexstring^ operator =(int data);
Code: Alles auswählen
error C2440: '=': 'int' kann nicht in 'hexstring ^' konvertiert werden
Redundanz macht wiederholen unnötig.
quod erat expectandum
quod erat expectandum
Re: Überladen des += Operators
Ja. Ich hätte wohl genau sagen sollen, dass ich mich auf das Beispiel mit *= von Xin's Homepage beziehe.fat-lobyte hat geschrieben:Tatsächlich hatte ich zuerst die Klasse als "class" definiert und die Membervariable auf private gesetzt. Dafür habe ich aber auch den überladenen stream operator als "friend" einauen müssen, und das wollte ich wegen etwaiger Verwirrungen vermeiden.
Als Struct definiert sind alle variablen automatisch public, es sei denn du führst explicit private oder protected zugriffsbeschränkungen ein.
Oder habe ich deine Frage missverstanden?
Code: Alles auswählen
class Fraction
{
private:
int Numerator;
int Denominator;
public:
Fraction( int num, int den ) : Numerator( num ), Denominator( den ) {}
Fraction & operator *=( Fraction & rhs );
};
Fraction & Fraction::operator *=( Fraction & rhs )
{
Numerator *= rhs.Numerator;
Denominator *= rhs.Denominator;
return *this;
}
Mir wurde gesagt das sei Verkapselung, eines der Grundprinzipien der OOP. Wahrscheinlich aber im Hinblick auf die kommenden Java-Jahre.fat-lobyte hat geschrieben:Das wäre die Java variante, getters und setters für jede kleine mini-variable. Glücklicherweise kann man in C++ intuitiveren Code schreiben.
Allzu viel kann ich noch nicht. Das sind eher die unteren Sachen. Das würde ein ziemliches C/C++ durcheinander werdenfat-lobyte hat geschrieben:Wieso denn das? Eine Sprache rein theoretisch zu lernen bringt nicht viel. Wenn du schon so topmotiviert bist und das ganze theoretisch machst, dann mach doch gleich ein "begleitendes" kleines Projekt dazu. Dabei wendest du immer das neu gelernte an. Ich kann dir zwar versprechen, dass du nur Müllcode fabrizieren wirst für den du dich später schämst (so wars zumindest bei mir), aber wenigstens lernst du einiges dabei.

Aber es stimmt schon. Ich sollte mehr üben...
- fat-lobyte
- Beiträge: 1398
- Registriert: Sa Jul 05, 2008 12:23 pm
- Wohnort: ::1
- Kontaktdaten:
Re: Überladen des += Operators
Bitte nimm Abstand von Compilererweiterungen. Wenn du auf deine VC++ Erweiterungen vermeidest, und ich meine GNU Erweiterungen kommen wir auf einen grünen Ast und können portabel Programmieren.cloidnerux hat geschrieben:Unter VC++ gibt es die möglichkeit etwas als eigenschaft zu definieren die eine get funktion hat, die automatisch aufgerufen wird wenn man darauf zugreift.
Ja, kann man. Erstens kannst du explizit den = operator überladen. Das muss allerdings wieder eine Memberfunktion der Klasse sein.cloidnerux hat geschrieben:Aber ich habe auch ncoh eine Frage:
KAnn man den "=" operator so überladen, das er der Classe z.B einen Int wert zuweiß, alos ungefähr so:Weil bie mir meldet er bei diesen Aufruf keinen fehler, aber wenn cih versuche nun einem Objekt dieser Klasse einen Int wert zuzuweisen meldet er mir immer:Code: Alles auswählen
hexstring^ operator =(int data);
Wieso?Code: Alles auswählen
error C2440: '=': 'int' kann nicht in 'hexstring ^' konvertiert werden
Zweite Möglichkeit: der Konstruktor. Wenn du einen Konstruktor hast, der eine bestimmte Variable als Parameter nimmt, dann kann man den Operator = auch mit der Klasse verwenden. ACHTUNG! Hier wird allerdings ein temporäres objekt aufgestellt! Sieh dir mal die zweite Version meines beispielsprogramms:
Code: Alles auswählen
#include <iostream>
struct MeineKlasse
{
int val;
// konstruktor, objekt wir mit int initialisiert
MeineKlasse(int _val)
: val(_val)
{ std::cout<<"Constructed\n";}
// ueberlade den += operator
MeineKlasse& operator += (int other)
{ val += other; return *this; }
~MeineKlasse()
{ std::cout<<"Destructed\n";}
};
// ueberlade den stream operator fuer ostream, damit wir cout benutzen koennen
std::ostream& operator << (std::ostream& os, const MeineKlasse& k)
{ return os<<k.val; }
int main()
{
MeineKlasse mein_objekt = 5;
std::cout<<"mein_objekt ist "<<mein_objekt<<'\n'; // verwende stream operator
// hier wird das alte objekt zerstört, ein neues erstellt und dann
// zugewiesen
mein_objekt = 11;
std::cout<<"mein_objekt ist jetzt "<<mein_objekt<<'\n';
return 0;
};
Kannst du mir bitte bitte sagen was das ^ da macht??
Und poste bitte den Code deiner "hexstring" Klasse!
Haters gonna hate, potatoes gonna potate.
- cloidnerux
- Moderator
- Beiträge: 3125
- Registriert: Fr Sep 26, 2008 4:37 pm
- Wohnort: Ram (Gibts wirklich)
Re: Überladen des += Operators
Also erstmal die ^ sind da weil es eine refernc klasse ist ....(.NET kram)
Ich Programmiere damit weil es sein muss.
hexstring.h:
hexstrng.cpp:
Ich Programmiere damit weil es sein muss.
hexstring.h:
Code: Alles auswählen
//hextsring.h
//stellt einen hexstring zur verfügung
#ifndef HEXSTRING_H
#define HEXSTRING_H
ref class hexstring
{
private:
System::String^ hex;
public:
System::String^ get() {
return hex;
};
property System::String^ default[int] {
System::String^ get(int idx);
//void set(int idx, hexstring^ data);
//void set(int idx, int data);
//void set(int idx, char data);
void set(int idx, System::String^ binärdata);
}
void set(int data);
void set(System::String^ data);
hexstring(int data);
hexstring(System::String^ binärdata);
void add_data(int data);
void add_data(System::String^ data);
static hexstring^ operator +(hexstring^ a, hexstring^ b);
static hexstring^ operator +(hexstring^ a, int data);
static hexstring^ operator +(hexstring^ a, System::String^ binärdata);
hexstring^ operator =(const char *data);
hexstring^ operator =(hexstring^ a);
hexstring^ operator =(int data);
hexstring^ operator =(System::String^ binärdata);
hexstring^ operator =(wchar_t *data);
hexstring^ operator +=(hexstring^ a);
hexstring^ operator +=(int data);
hexstring^ operator +=(System::String^ binärdata);
static bool operator ==(hexstring^ a, hexstring^ b);
static bool operator ==(hexstring^ a, int data);
static bool operator ==(hexstring^ a, System::String^ binärdata);
};
#endif
Code: Alles auswählen
//hexstring.cpp
//Definiert ale funktionen aus hextsring.h
#include "stdafx.h"
#include "hexstring.h"
using namespace System;
//
///////////////////////////////////////////
//Memberfunktionen
wchar_t tohex(wchar_t number)
{
if(number>15)
{
//MessageBox::Show("Nummer zu groß", "Hinweis");
return 0;
}
else
{
switch(number){
case 0: return '0';
case 1: return '1';
case 2: return '2';
case 3: return '3';
case 4: return '4';
case 5: return '5';
case 6: return '6';
case 7: return '7';
case 8: return '8';
case 9: return '9';
case 10: return 'A';
case 11: return 'B';
case 12: return 'C';
case 13: return 'D';
case 14: return 'E';
case 15: return 'F';
}
}
return 'Z';
}
int toint(wchar_t number)
{
switch(number)
{
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
case 'A': return 10;
case 'B': return 11;
case 'C': return 12;
case 'D': return 13;
case 'E': return 14;
case 'F': return 15;
}
return 0;
}
System::String^ chartohex(unsigned char a)
{
String^ result;
result=tohex(a/16).ToString();
result+=tohex(a%16).ToString();
return result;
}
String^ inttohex(unsigned long i)
{
String^ result="";
unsigned long tmp = i;
for(int i = 7; i > 0; i--)
{
result+=tohex(tmp/(16^i)); //Wie häufig kommt 16î vor?
tmp=(tmp%16^i); //Den rest der Division speichern
}
result+=tohex(tmp); //Den rest in result speichern
return result;
}
String^ stringtohex(System::String^ binärdata)
{
String^ tmp;
for(int i=0; i < binärdata->Length;i++)
{
tmp+=chartohex(binärdata[i]);
}
return tmp;
}
int hextoint(String^ hexstring)
{
int tmp=0;
for(int i=0; i<hexstring->Length; i+=2)
{
tmp+=(toint(hexstring[i]<<4)+toint(hexstring[i+1]));
}
return tmp;
}
//
///////////////////////////////////////////////////
//Konstruktor
hexstring::hexstring(int data)
{
hex = inttohex(data);
}
hexstring::hexstring(String^ binärdata)
{
hex = stringtohex(binärdata);
}
//
/////////////////////////////////////////////////
//Funktionen zum Manipulieren des Inhaltes des Hexstrings
void hexstring::add_data(int data)
{
hex += inttohex(data);
}
void hexstring::add_data(String^ binärdata)
{
hex+=stringtohex(binärdata);
}
void hexstring::set(int data)
{
hex = inttohex(data);
}
void hexstring::set(String ^data)
{
hex = stringtohex(data);
}
//
/////////////////////////////////////////////////
//Indexer:
String^ hexstring::default::get(int idx) //gibt das Zeichenpaar für das Byte an stelle idx aus
{
if((idx*2)>hex->Length) return "00";
else return hex->Substring(idx*2, 2);
}
//void hexstring::default::set(int idx, hexstring^ data)
//{
// hex->Replace(hex->Substring(idx*2, data->hex->Length), data);
//}
//
//void hexstring::default::set(int idx, int data)
//{
// hex->Replace(hex->Substring(idx*2, 8), inttohex(data));
//}
//
//void hexstring::default::set(int idx, char data)
//{
// hex->Replace(hex->Substring(idx*2,2), chartohex(data));
//}
void hexstring::default::set(int idx, String^ binärdata)
{
hex->Replace(hex->Substring(idx*2, binärdata->Length), stringtohex(binärdata));
}
//
/////////////////////////////////////////////////
//Operatordefinitionen
//+:
hexstring^ hexstring::operator +(hexstring ^a, hexstring ^b)
{
return gcnew hexstring(a->hex + b->hex);
}
hexstring^ hexstring::operator +(hexstring ^a, int data)
{
return gcnew hexstring(a->hex + inttohex(data));
}
hexstring^ hexstring::operator +(hexstring ^a, System::String ^binärdata)
{
return gcnew hexstring(a->hex + stringtohex(binärdata));
}
//
//////////////////////////////////////////
//+=:
hexstring^ hexstring::operator +=(hexstring ^a)
{
hex+=a->hex;
return this;
}
hexstring^ hexstring::operator +=(int data)
{
hex += inttohex(data);
return this;
}
hexstring^ hexstring::operator +=(System::String ^binärdata)
{
hex += stringtohex(binärdata);
return this;
}
//
//////////////////////////////////////////
//=:
hexstring^ hexstring::operator =(hexstring ^a)
{
hex = a->hex;
return this;
}
hexstring^ hexstring::operator =(int data)
{
hex = inttohex(data);
return this;
}
hexstring^ hexstring::operator =(String ^binärdata)
{
hex = stringtohex(binärdata);
return this;
}
hexstring^ hexstring::operator =(wchar_t *data)
{
hex = Convert::ToString(*data);
return this;
}
hexstring^ hexstring::operator =(const char *data)
{
hex = Convert::ToString(*data);
return this;
}
//
//////////////////////////////////////////
//==:
bool hexstring::operator ==(hexstring^ a, hexstring^ b)
{
if(a->hex == b->hex) return true;
else return false;
return false;
}
bool hexstring::operator ==(hexstring^ a, int data)
{
if(a->hex == inttohex(data)) return true;
else return false;
return false;
}
bool hexstring::operator ==(hexstring^ a, String^ binärdata)
{
if(a->hex == stringtohex(binärdata))return true;
else return false;
return false;
}
Redundanz macht wiederholen unnötig.
quod erat expectandum
quod erat expectandum
- fat-lobyte
- Beiträge: 1398
- Registriert: Sa Jul 05, 2008 12:23 pm
- Wohnort: ::1
- Kontaktdaten:
Re: Überladen des += Operators
Achso... Naja das ist etwas, was ich ein wenig obskur in C++ finde. Da das andere Objekt ja vom "gleichen" typ ist wie das jetzige, wird auf die Variablen auch nur quasi "intern" zugegriffen. Das bedeutet, private bezieht sich nicht auf das Objekt selbst (also auf Zeiger auf das Objekt) sondern auf den Typ des Objekts. Das gilt aber nur für Objekte gleichen Typs. Ich bin mir nichtmal sicher, ob man das auch mit funktionen machen kann die nicht der Konstruktor sind.dani93 hat geschrieben: Ja. Ich hätte wohl genau sagen sollen, dass ich mich auf das Beispiel mit *= von Xin's Homepage beziehe.Code: Alles auswählen
...
Darf ich mal fragen, wozu man eigentlich getters und setters definiert, anstatt die Variable gleich Public zu machen?? Bei Kapselung gehts darum dinge Abzukapseln, was bei get/set eindeutig nicht der Fall ist. Eine andere geschichte sind allerdings "read only" member. Hier kann man durch getVariable() const Funktionen schon dinge Abkapseln.dani93 hat geschrieben:Mir wurde gesagt das sei Verkapselung, eines der Grundprinzipien der OOP. Wahrscheinlich aber im Hinblick auf die kommenden Java-Jahre.
Haters gonna hate, potatoes gonna potate.