2016-11-22 3 views
1

Gibt es irgendwelche "Regeln" für welche Art von Rückgabetyp Member vs Non-Member-Funktionen haben sollte?Member vs Nichtmitgliedsfunktionen, Rückkopie oder Referenz?

Ich baue eine komplexe Klasse und ich dachte, Elementfunktionen würden Rückgabetyp Referenzen sein und Nichtmitglied würde Kopien sein. Ist das richtig?

complex.h Referenz:

#include <iostream> 
#include <string> 

#ifndef COMPLEX_H 
#define COMPLEX_H 


class Complex { 

    public: 
    double real; 
    double imaginary; 


    Complex(); 
    Complex(const double real); 
    Complex(const double real, const double imaginary); 
    Complex(const Complex &rhs); 

    Complex& operator *= (const Complex&); 
    Complex& operator += (const Complex&); 
    Complex& operator /= (const Complex&); 
    Complex& operator -= (const Complex&); 
    Complex& operator = (const Complex&); 

}; 

class Complex; 

double abs(const Complex& c); 

Complex operator * (const Complex& c1, const Complex& c2); 
Complex operator/(const Complex& c1, const Complex& c2); 
Complex operator + (const Complex& c1, const Complex& c2); 
Complex operator - (const Complex& c1, const Complex& c2); 

bool operator == (const Complex& c1, const Complex& c2); 
bool operator != (const Complex& c1, const Complex& c2); 

std::istream& operator >> (std::istream& in, Complex& c); 
std::ostream& operator << (std::ostream& out, const Complex& c); 

Complex operator ""_i(long double arg); 
Complex operator ""_i(unsigned long long arg); 

#endif 
+2

Verwandt, Sie könnten wahrscheinlich einige ziemlich gute Richtlinien aus der Klasse ['std :: complex'] (http://en.cppreference.com/w/cpp/numeric/complex) bekommen, die Sie scheinbar neu erfinden. Der Zufall ist die Standard-Bibliothek Architekten haben einige durchdachte Entscheidungen getroffen. – WhozCraig

Antwort

2

Es ist nicht wirklich über das Mitglied gegen Nicht-Mitglied. Sie haben Verweise in Ihren Mitgliedsfunktionen zurückgegeben, da sie den Wert this tatsächlich geändert haben.

Betrachten Sie den folgenden Code ein:

Complex c1, c2, c3; 
// ... 
(c3 *= c2) += c1; 

Hier c3 *= c2 ausgewertet werden, dann operator+= wird auf das Ergebnis mit c1 als Parameter aufgerufen werden. Wenn Sie eine Kopie anstelle einer Referenz für c3 *= c2 zurückgeben, wird die nächste angewendete diese zurückgegebene Kopie anstelle von c3 ändern, was nicht zu erwarten ist.

Beachten Sie, dass Sie auch Ihre anderen Operatoren als Memberfunktionen erklärt haben könnten, nur gegen Kopie die Referenz zu zeigen ist nicht gegen Nicht-Mitglied zu Mitglied bezogen werden:

class Complex { 

    // ... 

    Complex& operator *= (const Complex&); 
    Complex& operator += (const Complex&); 
    Complex& operator /= (const Complex&); 
    Complex& operator -= (const Complex&); 
    Complex& operator = (const Complex&); 

    Complex operator * (const Complex& c2); 
    Complex operator/(const Complex& c2); 
    Complex operator + (const Complex& c2); 
    Complex operator - (const Complex& c2); 

}; 
2

Sie haben, was Sie suchen erwarte ich vom Ergebnis, wenn Sie Ihren Operator anrufen.

Zum Beispiel, wenn Sie den Operator * verwenden, werden Sie erwarten haben vielleicht

//Some Complex instances c1 and c2 already created 
Complex c3 = c1 * c2; 

Sie würden nicht C1 oder C2 geändert haben wollen. Die Kopie hier ist also nett.

Wenn Sie jedoch den Operator * = verwenden, erwarten Sie, dass das Ergebnis Ihre komplexe Instanz ändert, für die der Operator aufgerufen wurde. Hier ist eine Referenz besser, da Sie den Kopierkonstruktor und den Destruktor vermeiden.

Also das Beispiel, das Sie gaben, ist ok.

2

Wie oben erwähnt, ist die wichtige Frage nicht, ob dies ein Mitglied oder Nichtmitglied ist, sondern ob der zurückgegebene Wert eine neue Instanz ist oder nicht.

Jede Operation, die das Objekt selbst ändert (wie ++, + =, - =, ...) sollte eine Referenz auf dasselbe Objekt zurückgeben. Auf der anderen Seite muss jede Operation, die zu einem anderen Objekt führt (wie binary +, -, etc ...), ein neues Objekt erstellen, da die ursprünglichen Operanden niemals geändert werden sollten.

Darüber hinaus können einige binäre Operatoren Mitglieder sein (z. B. komplex + int), während andere außerhalb der Klasse definiert sein müssen (z. B. int + komplex). Natürlich möchten Sie, dass sich diese beiden Operationen identisch verhalten.

Verwandte Themen