Operator '=' überladen

Hallo,

Vorweg: Ich bin neuling was cpp angeht und versuche mir gerade die Sprache anzueignen

Problem:
Ich versuche den Operator für eine Klasse zu überladen, sodass ich einer String Var den Standardwert der Klasse übergeben kann.
Ich habe das auch bereits innerhalb der Klasse versucht. Funktioniert auch nur eben nur in eine Richtung - sprich eine Zuweisung wie classTyp = stringvar funtioniert, aber stringvar = classTyp bekomme ich eine Fehlermeldung. Muss ich den Operator für den String überladen und wie stell’ ich das am Sinnvollsten an??

Bin für jede Hilfe Dankbar

Enrico

Also wenn ich dich richtig verstanden habe, willst du einen String in eine Variable kopieren oder? Sowas geht mit ‚=‘ sowieso nicht. Dazu brauchst du die String-Funktion strcpy(). Sh. hier: http://www.cplusplus.com/reference/clibrary/cstring/…

Ich hoffe ich habe dich richtig verstanden.

Hallo Enrico,

Zuweisung wie classTyp = stringvar funtioniert, aber stringvar
= classTyp bekomme ich eine Fehlermeldung.

Das hat den Grund, daß Du für „classTyp“ das ‚=‘ überladen hast, aber nicht für „stringvar“.

Muss ich den
Operator für den String überladen und wie stell’ ich das am
Sinnvollsten an??

Musst Du, am besten so:

class stringvar
 {
 public:
 const stringvar& operator= (const classTyp &cl);
 };

const stringvar& stringvar::operator= (const classTyp &cl)
 {
 if (&cl != this)
 {
 // hier die Zuweisungen einfuegen
 }

 return \*this;
 }

Der Rückgabewert muss nicht zwingend so sein, hat aber den Vorteil, dass Du dann auch so was machen kannst:

name = name = name;

Der ‚=‘ ist einer von den vier Operatoren, die man nur in der Klasse überladen kann, nicht global. Wenn Du einen Char-Zeiger als Member zu kopieren hast, ist das mit der strcpy() schon eine Lösung. Achte bitte darauf, daß das aktuelle Objekt (*this) seinen eigenen Speicher abkriegt dafür (= new), damit nicht zwei Zeiger auf den selben Speicher zugreifen.

wünsche gutes Gelingen
lg
Martin B

naja gemint war das so:

#include 
#include 
#include "myClass"
using namespace std;
int main()
{
 string str;
 myclass mc;
 mc.setData("irgendeinText") /\*der Text wird einer
 Gültigkeitsprüfung unterzogen
 und in einer privaten string-var
 gespeichert \*/
 str=mc; //der aufruf soll funktionieren;
 mc=str; //dieser ebenfalls / als bequemer ersatz für mc.setData(str);
}

Aber Danke schon mal für die hilfreichen Antworten

Enrico

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo,

Ich versuche den Operator für eine Klasse zu überladen, sodass
ich einer String Var den Standardwert der Klasse übergeben
kann.
Ich habe das auch bereits innerhalb der Klasse versucht.
Funktioniert auch nur eben nur in eine Richtung - sprich eine
Zuweisung wie classTyp = stringvar funtioniert, aber stringvar
= classTyp bekomme ich eine Fehlermeldung. Muss ich den
Operator für den String überladen und wie stell’ ich das am
Sinnvollsten an??

Das hängt davon ab, was sinnvoller ist. Du kannst einmal

class stringvar {
 stringvar& operator=(classTyp const& value);
};

die Aufgabe der Klasse ‚stringvar‘ geben oder andersherum

class classTyp {
 operator stringvar();
};

der Klass ‚classTyp‘ erlauben, automatisch statt sich selbst ein Objekt der Klasse ‚stringvar‘ zurückzugeben. Diese Konvertierung verläuft *automatisch* (wie in C von int zu double).
Ich habe als Beispiel mal eine Klasse ‚Bruch‘ geschrieben, die die rationalen Zahlen repräsentiert. Die hat eine Konvertierung

class Bruch {
 Bruch(int);
 Bruch(int, int);
 operator double();
};

und so kann ich

 sin(Bruch(2,3));

und so aufrufen. Vorsicht ist bei der Typumwandlung:

 Bruch(1, 2) + 2 --\> Typ Bruch, da '2' automatisch in 'Bruch' umgewandelt wird (Konstruktor 'Bruch(int)')
 Bruch(1, 2) + 2.0 --\> Typ double, da 'Bruch' automatisch in 'double' umgewandelt wird.

Gruß
Diether

Hallo Diether,

class classTyp {
operator stringvar();
};

Würde ich nicht machen. Das scheint so bequem, hat aber Haare auf den Zähnen:
irgendwann willst Du so ein Ding, als Template-Typ, in einen Container stecken, und der Compiler kriegt dann die Krise, weil er nicht weiss, ob das ein „classTyp“ oder ein „stringvar“ sein soll („zweifelhaft“). Mit meiner Empfehlung nicht.

class Bruch {
Bruch(int);
Bruch(int, int);
operator double();
};

und so kann ich

sin(Bruch(2,3));

Gut, das geht so. Ich kann das selbe aber auch mit einer ordinären getAny() machen, fast um das selbe Geld:

sin( (Bruch(2,3)).getAny() );

und so aufrufen. Vorsicht ist bei der Typumwandlung:

Bruch(1, 2) + 2 --> Typ Bruch, da ‚2‘ automatisch in
‚Bruch‘ umgewandelt wird (Konstruktor ‚Bruch(int)‘)
Bruch(1, 2) + 2.0 --> Typ double, da ‚Bruch‘
automatisch in ‚double‘ umgewandelt wird.

Na, die zweite Zeile wäre OK, aber: die „2“ wird in „Bruch“ umgewandelt? Deinen Optimismus in Ehren, aber warum sollte ein Compiler soetwas machen? Hat die „2“ jetzt einen

operator Bruch() {}

?
Oder habe ich Dich da missverstanden?

lg
Martin B

Hallo Martin,

Würde ich nicht machen. Das scheint so bequem, hat aber Haare
auf den Zähnen:
irgendwann willst Du so ein Ding, als Template-Typ, in einen
Container stecken, und der Compiler kriegt dann die Krise,
weil er nicht weiss, ob das ein „classTyp“ oder ein
„stringvar“ sein soll („zweifelhaft“). Mit meiner Empfehlung
nicht.

Ich hätte betonen sollen, daß man das vorsichtig verwenden soll. Ich denke, bei der Bruch-Klass ist das in Ordnung.

sin(Bruch(2,3));

Gut, das geht so. Ich kann das selbe aber auch mit einer
ordinären getAny() machen, fast um das selbe Geld:
sin( (Bruch(2,3)).getAny() );

Dafür habe ich doch keine Objektorientierung. Ich will mich gerade nicht darum kümmern, ob ich direkt ein double übergebe oder einen Bruch.

und so aufrufen. Vorsicht ist bei der Typumwandlung:

Bruch(1, 2) + 2 --> Typ Bruch, da ‚2‘ automatisch in
‚Bruch‘ umgewandelt wird (Konstruktor ‚Bruch(int)‘)
Bruch(1, 2) + 2.0 --> Typ double, da ‚Bruch‘
automatisch in ‚double‘ umgewandelt wird.

Na, die zweite Zeile wäre OK, aber: die „2“ wird in „Bruch“
umgewandelt? Deinen Optimismus in Ehren, aber warum sollte ein
Compiler soetwas machen? Hat die „2“ jetzt einen

operator
Bruch() {}

?
Oder habe ich Dich da missverstanden?

Nein, Bruch hat einen impliziten Konstruktor: Bruch(int i), der reicht aus:

dknof@sybille:t$ cat Bruch.cpp 
#include 

class Bruch {
 public:
 Bruch(int const i) :
 z(i), n(1) { }
 Bruch(int const z, int const n) :
 z(z), n(n) { }
 /\*
 operator double()
 { return (static\_cast(this-\>z) / this-\>n); }
 \*/

 int z, n;
};
Bruch operator+(Bruch const& b1, Bruch const& b2)
{ return Bruch(b1.z \* b2.n + b1.n \* b2.z, b1.n \* b2.n); }
std::ostream& operator

Probleme gibt es, wenn ich auch den operator double dazuschalte, da dann der Compiler nicht zwischen operator+(double, int) und operator+(Bruch, Bruch) entscheiden kann. Ist hingegen der Konstruktor 'Bruch(int)' explizit: 'explicit Bruch(int)', dann wird der double-Konverter genommen, da ich die int-\>Bruch-Konvertierung explizit angeben muß:


    
    dknof@sybille:t$ diff Bruch.cpp Bruch2.cpp; g++ -Wall Bruch2.cpp && ./a.out
    5c5
     explicit Bruch(int const i) :
    9d8
     std::cout (c) + b 
    
    Praktisch habe ich für meine Bruch-Klasse mit die Kombinationen Bruch und int (bei den einzelnen Operatoren) separat definiert und die double-Typkonvertierung verwendet.
    
    
    Gruß
    Diether