‚Freund‘ Funktionen und << Betreiber Überlastung: Was ist der richtige Weg, um einen Operator für eine Klasse zu überlasten?

StackOverflow https://stackoverflow.com/questions/2828280

Frage

In einem Projekt arbeite ich an, ich habe eine Score Klasse, wie unten definiert in score.h. Ich versuche, es so zu überlasten, wenn ein << Betrieb auf sie durchgeführt wird, _points + " " + _name gedruckt wird.

Hier ist, was ich versucht zu tun:

ostream & Score::operator<< (ostream & os, Score right)
{
    os << right.getPoints() << " " << right.scoreGetName();
    return os;
}

Hier sind die Fehler zurückgegeben:

score.h(30) : error C2804: binary 'operator <<' has too many parameters

(Dieser Fehler erscheint 4 mal, tatsächlich)

schaffte ich es zum Laufen zu bringen, indem die Überlastung als Freund Funktion erklärt:

friend ostream & operator<< (ostream & os, Score right);

Und das Entfernen des Score:: aus der Funktionsdeklaration in score.cpp (effektiv nicht als Mitglied erklärt).

Warum funktioniert das, aber das ehemalige Stück Code nicht?

Vielen Dank für Ihre Zeit!

Bearbeiten

Ich löschte alle auf die Überlastung erwähnen auf der Header-Datei ... aber ich bekomme den folgenden (und einzigen) Fehler. binary '<<' : no operator found which takes a right-hand operand of type 'Score' (or there is no acceptable conversion) Wie kommt mein Test, in main () kann nicht über die entsprechende Überlastung finden? (Es ist nicht das enthält, überprüfte ich)

Im Folgenden finden Sie den vollen score.h

#ifndef SCORE_H_
#define SCORE_H_

#include <string>
#include <iostream>
#include <iostream>

using std::string;
using std::ostream;

class Score
{

public:
    Score(string name);
    Score();
    virtual ~Score();
    void addPoints(int n);
    string scoreGetName() const;
    int getPoints() const;
    void scoreSetName(string name);
    bool operator>(const Score right) const;

private:
    string _name;
    int _points;

};
#endif
War es hilfreich?

Lösung

Hinweis: Sie könnten auf dem Betreiber Überlastung FAQ zu suchen.


Binäre Operatoren können entweder Mitglieder ihrer linken Argument der Klasse oder kostenlose Funktionen sein. (Einige Betreiber, wie Zuordnung, müssen Mitglieder sein.) Da der Stream Betreiber linke Argument ein Strom ist, Strom Betreiber entweder Mitglieder der Stream-Klasse oder kostenlose Funktionen sein. Die kanonische Weise operator<< für jede Art zu implementieren, ist dies:

std::ostream& operator<<(std::ostream& os, const T& obj)
{
   // stream obj's data into os
   return os;
}

Beachten Sie, dass es nicht eine Elementfunktion. Beachten Sie auch, dass es die Aufgabe übernimmt pro const Bezug zu streamen. Das ist, weil du nicht das Objekt, um kopieren wollen, dass es zu streamen und Sie nicht möchten, dass das Streaming es entweder zu verändern.


Manchmal möchten Sie Objekte, deren Interna streamen nicht zugänglich sind durch ihre Klasse öffentliche Schnittstelle, so kann der Bediener nicht an ihnen. Dann haben Sie zwei Möglichkeiten: Entweder ein öffentliches Mitglied in die Klasse setzen, die funktioniert das Streaming

class T {
  public:
    void stream_to(std::ostream&) const {os << obj.data_;}
  private:
    int data_;
};

und Anruf, dass vom Betreiber:

inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
   obj.stream_to(os);
   return os;
}

oder den Betreiber macht ein friend

class T {
  public:
    friend std::ostream& operator<<(std::ostream&, const T&);
  private:
    int data_;
};

so, dass es die Klasse private Teile zugreifen können:

inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
   os << obj.data_;
   return os;
}

Andere Tipps

Angenommen, Sie haben einen Operator Überlastung für + schreiben wollte, so dass Sie zwei Score Objekte zueinander hinzufügen könnte, und ein anderer, damit Sie eine int zu einem Score hinzufügen könnte, und ein drittes, so dass Sie eine Score zu einem int hinzufügen könnte. Diejenigen, die ein Score die ersten Parameter können Elementfunktionen Score sein. Aber die, wo ein int der erste Parameter ist, kann nicht Mitglied Funktionen von int worden, nicht wahr? Um Ihnen dabei zu helfen, sind Sie erlaubt, sie als freie Funktionen zu schreiben. Das ist, was mit diesem << Betreiber geschieht, können Sie keine Member-Funktion ostream hinzufügen, so dass Sie eine kostenlose Funktion schreiben. Das ist, was es bedeutet, wenn Sie den Score:: Teil wegzunehmen.

Nun, warum hat es eine friend sein? Es funktioniert nicht. Sie anrufen nur öffentliche Methoden (getPoints und scoreGetName). Sie sehen eine Menge Freund Betreiber, da sie direkt auf die privaten Variablen sprechen mögen. Es ist in Ordnung von mir, das zu tun, weil sie von der Person maintaing die Klasse geschrieben und gepflegt. Nur nicht den Freund Teil mit dem Element-Funktion-vs-Freifunktionsteil sich verfahren werden.

Sie sind immer Fehler Kompilation wenn operator<< eine Member-Funktion in dem Beispiel, weil Sie eine operator<< erstellen, von einer Score als ersten Parameter übernimmt (das Objekt der Methode des auf genannt wird), und dann einen zusätzlichen Parameter geben am Ende.

Wenn Sie einen binären Operator sind aufrufen, die als Mitglied Funktion deklariert ist, ist die linke Seite des Ausdrucks das Objekt die Methode der aufgerufen wird. z.B. a + b Macht funktioniert wie folgt:

A a;
B b

a.operator+(b)

Es ist typischerweise bevorzugt Nichtmitglied binäre Operatoren (und in einigen Fällen zu verwenden - zum Beispiel operator<<for ostream ist der einzige Weg, es zu tun in diesem Fall a + b funktionieren könnte wie folgt aus:.

A a;
B b

operator+(a, b);

Hier ist ein vollständiges Beispiel in beiden Richtungen, es zu tun ist; main () ausgeben wird '55' dreimal:

#include <iostream>

struct B
{
    B(int b) : value(b) {}
    int value;
};


struct A
{
    A(int a) : value(a) {}
    int value;

    int operator+(const B& b) 
    {
        return this->value + b.value;
    }
};

int operator+(const A& a, const B& b)
{
    return a.value + b.value;
}

int main(int argc, char** argv)
{
    A a(22);
    B b(33);

    std::cout << a + b << std::endl;
    std::cout << operator+(a, b) << std::endl;
    std::cout << a.operator+(b) << std::endl;

    return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top