Richtige Syntax bei Operatorüberladung, wann sind "friend", "const", "&" nötig?

mrs_schokokeks

Grünschnabel
Hi, also die Aufgabe lautet:

Die Anweisungen:

Code:
Bruch a( 5 );
Bruch b( 1, 2 );
Bruch c( 1, 4 );
Bruch d( 115, -391 );
Bruch e( -37*234, -37*432 );
cout << a << b << c << d << e << endl;
cout << b + c << endl;
cout << 8 + e << endl;
cout << d * e << endl;

erzeugen die Ausgabe:

5/1 1/2 1/4 -5/17 13/24
3/4
205/24
-65/408


Dazu habe ich folgende Lösung:

Code:
class Bruch
{private:
int z;
int n;


public:
class BruchExceptionNennerNull {};

Bruch( int zaehler, int nenner = 1 ) 
{
if(nenner == 0)
throw BruchExceptionNennerNull();
z = zaehler;
n = nenner;

if( n < 0 )
{
z = -z;
n = -n;
}

}


friend ostream& operator<<(ostream& os, const Bruch& br);


friend Bruch operator+( const Bruch& links, const Bruch& rechts);


Bruch operator*(const Bruch& rechts)

{
return Bruch( z * rechts.z, n * rechts.n);
}
};



ostream& operator<<(ostream& os, const Bruch& br)
{
return os << br.z << "/" << br.n << " ";
}
Bruch operator+(const Bruch& links, const Bruch& rechts)
{
return Bruch( links.z * rechts.n + rechts.z * links.n,
links.n * rechts.n );
}



Ich verstehe nicht, wann man "friend", "const" und "&" verwenden soll!



Und hier sind Auszüge aus einem anderen Programm:


Code:
class Hms
{
	private: 
		long t;


	public:

Hms& operator++(Hms &obj)	
{
	obj.t++;
	return obj;								
}
};

Hier wird "&" vor "operator" verwendet.

Und bei

Code:
class Hms
{
	private: 
		long t;

	public:
friend Hms operator+(long s, const Hms &obj)
{
	Hms tmp( (s + obj.t) );

	return tmp;

}
};

steht kein "&".

Ok, es ist vielleicht hier nicht ganz klar, wozu die gut sind ^^ aber es gibt ja bestimmte Fälle, wo "friend", "const" und "&" geschrieben werden müssen. Und die kann ich irgendwie nicht unterscheiden und bin immer wieder aufs Neue verwirrt...
Hoffentlich könnt ihr mir das ganz klar und einfach erklären!
Danke!
 
Moin,

Code:
class Hms
{
	private: 
		long t;

	public:
friend Hms operator+(long s, const Hms &obj)
{
	Hms tmp( (s + obj.t) );

	return tmp;

}
};
steht kein "&".
Doch: const Hms &obj .... Zeile 7 .....

Ok, es ist vielleicht hier nicht ganz klar, wozu die gut sind ^^ aber es gibt ja bestimmte Fälle, wo "friend", "const" und "&" geschrieben werden müssen. Und die kann ich irgendwie nicht unterscheiden und bin immer wieder aufs Neue verwirrt...
Hoffentlich könnt ihr mir das ganz klar und einfach erklären!
Danke!

zu "friend":
C++:
friend Klassenname;
friend Funktionsdeklarator;
Dieses Schlüsselwort teilt dem Compiler mit, daß eine Funktion oder Klasse Zugriff auf die als private oder protected deklarierten Elemente der eigenen Klasse hat.

Eine Klasse, bei der sämtliche Methoden Zugriff auf die Elemente einer anderen Klasse haben, wird als Friend-Klasse bezeichnet.
Friend-Klassen müssen innerhalb der Klasse als solche deklariert werden, die Zugriff auf ihre Elemente gewährt

Das Schlüsselwort const wird verwendet, um Konstanten (schreibgeschützte Werte) zu erzeugen. Nach der Initialisierung kann eine Konstante nicht mehr verändert aber wie eine Variable gelesen werden.

Google mal einfach nach dem Begriffen oder schau in ein C++-Buch, da sind diese Grundlagen alle lang und breit erklärt :p

Gruß
Klaus
 
Zuletzt bearbeitet von einem Moderator:
Danke für die Antwort!

Ich meinte, kein "&" vor "operator+":

Code:
class Hms
{
    private: 
        long t;
 
    public:
friend Hms operator+(long s, const Hms &obj)  // nicht friend Hms& operator+(long s,  const Hms &obj) !

{
    Hms tmp( (s + obj.t) );
 
    return tmp;
 
}
};

Und was bedeutet das & in der Klammer bei (const Hms &obj)?

^^ Hab mich schon fast totgegoogelt, aber z.B. bei der ersten Aufgabe:

friend Bruch operator+( const Bruch& links, const Bruch& rechts);
Bruch operator*(const Bruch& rechts);

Wieso bei einem friend und bei anderem nicht? Bruch operator* greift doch auch auf private member zu?

:eek:
 
Hi.
Ich meinte, kein "&" vor "operator+":

Code:
class Hms
{
    private: 
        long t;
 
    public:
friend Hms operator+(long s, const Hms &obj)  // nicht friend Hms& operator+(long s,  const Hms &obj) !

{
    Hms tmp( (s + obj.t) );
 
    return tmp;
 
}
};

Und was bedeutet das & in der Klammer bei (const Hms &obj)?
Das & bedeutet, dass obj eine Referenz auf ein Hms ist. :google: "Referenztypen c++"


friend Bruch operator+( const Bruch& links, const Bruch& rechts);
Bruch operator*(const Bruch& rechts);

Wieso bei einem friend und bei anderem nicht? Bruch operator* greift doch auch auf private member zu?
Der entscheidende Unterschied ist, dass operator* eine Memberfunktion (sprich: Methode) ist, und operator+ nicht. Deshalb kann operator+ auch nicht auf private oder protected Member zugreifen.

Eigentlich ist diese Schreibweise auch etwas ungewöhnlich, normalerweise verwendet man es so:
C++:
class A {
  int m_value;
public:
  friend A operator+(const A&, const A&);
};

A operator+(const A& x, const A& y) {
  std::cout << x.m_value; // OK: ist ein Freund von A
}
Der operator+ hat im Grunde gar nichts mit der Klasse zu tun, außer dass eine "Freundschaft" zwischen der Klasse und dem Operator besteht.

\edit: Bzgl. deiner Frage warum der Operator ein B und kein B& zurückgibt: eine Funktion kann nur eine Referenz zurückgeben wenn bereits ein Objekt existiert, der Operator erzeugt aber ein neues Objekt (das Ergebnis der "Addition" von 2 A:
C++:
A f1() {
  A a;
  return a; // OK: ein neues A
}

A& f2() {
  A a;
  return a; // ERROR: gibt eine Referenz auf ein lokales Objekt zurück (führt zum Absturz)
}

A& f3() {
  A* a = new A();
  return *a; // ERROR: gibt eine Referenz auf ein dyn. erzeugtes Objekt zurück (Speicherleck)
}
Konstante Referenzen als Parameter verwendet man immer dann, wenn innerhalb der Methode oder Funktion der Parameter nicht verändert wird. Das hat den Vorteil, das man auch temporäre Objekte übergeben kann:
C++:
class B {
  int m_value;
public:
  B(int i) : m_value(i);
  void set_value(int v) { m_value = v; }
};

void f1(B& x) {
  x.set_value(1); // OK
}

void f2(const B& x) {
  x.set_value(2); // ERROR: x ist konstant!
}

void f3(B x) {
  x.set_value(3); // OK
}

int main() {
  B b;
  b.set_value(-1);

  f1(b); // OK
  // b.m_value ist jetzt == 1
  f1(33); // ERROR

  f2(b); // OK
  f2(33); // OK (erzeugt temporäres B über Konstruktor)

  f3(b); // OK, aber erzeugt Kopie von B (ineffizient!)
  // b.m_value ist immer noch == 1
  f3(33); // OK
}
Gruß
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück