2012-05-24 2 views
64

ahOperator << muss nehmen genau ein Argument

#include "logic.h" 
... 

class A 
{ 
friend ostream& operator<<(ostream&, A&); 
... 
}; 

logic.cpp

#include "a.h" 
... 
ostream& logic::operator<<(ostream& os, A& a) 
{ 
... 
} 
... 

Wenn ich kompilieren, heißt es:

std :: ostream & Logik :: Bediener < < (Std :: ostream &, A &) 'muss genau eins nehmen Streit.

Was ist das Problem?

Antwort

90

Das Problem ist, dass man es in der Klasse definieren, die

a) bedeutet, dass das zweite Argument implizit (this) und

b) wird es nicht tun, was Sie tun wollen, nämlich erweitern std::ostream.

Sie haben es als freie Funktion zu definieren:

class A { /* ... */ }; 
std::ostream& operator<<(std::ostream&, const A& a); 
+7

Außerdem deklariert er es als eine Friend-Funktion und definiert es als ich mber-Funktion. – asaelr

40

Ein Freund Funktion ist kein Mitglied Funktion, so dass das Problem ist, dass Sie operator<< als Freund von A erklären:

friend ostream& operator<<(ostream&, A&); 

dann versuchen, es als eine Elementfunktion der Klasse logic

ostream& logic::operator<<(ostream& os, A& a) 
      ^^^^^^^ 
zu definieren

Sind Sie verwirrt darüber, ob logic eine Klasse oder ein Namespace ist?

Der Fehler ist, weil Sie versucht haben, ein Mitglied operator<< nimmt zwei Argumente zu definieren, was bedeutet es drei Argumente einschließlich der impliziten this Parameter übernimmt. Der Operator kann nur zwei Argumente annehmen, so dass beim Schreiben von a << b die beiden Argumente a und b sind.

Sie wollen ostream& operator<<(ostream&, const A&) als nicht -Mitglied Funktion definieren, auf jeden Fall nicht als Mitglied der logic, da es nichts mit dieser Klasse zu tun hat!

std::ostream& operator<<(std::ostream& os, const A& a) 
{ 
    return os << a.number; 
} 
0

Ich stieß auf dieses Problem mit Templat-Klassen. Hier ist eine allgemeinere Lösung, die ich benutzen musste:

template class <T> 
class myClass 
{ 
    int myField; 

    // Helper function accessing my fields 
    void toString(std::ostream&) const; 

    // Friend means operator<< can use private variables 
    // It needs to be declared as a template, but T is taken 
    template <class U> 
    friend std::ostream& operator<<(std::ostream&, const myClass<U> &); 
} 

// Operator is a non-member and global, so it's not myClass<U>::operator<<() 
// Because of how C++ implements templates the function must be 
// fully declared in the header for the linker to resolve it :(
template <class U> 
std::ostream& operator<<(std::ostream& os, const myClass<U> & obj) 
{ 
    obj.toString(os); 
    return os; 
} 

Jetzt: * My toString() Funktion kann nicht inline sein, wenn es in cpp versteckt werden soll. * Sie sind mit etwas Code in der Kopfzeile stecken, ich konnte es nicht loswerden. * Der Operator ruft die Methode toString() auf, die nicht inline ist.

Der Operator < < kann in der Friend-Klausel oder außerhalb der Klasse deklariert werden. Beide Optionen sind hässlich.:(

Vielleicht bin ich etwas Missverständnis oder fehlt, sondern nur voraus erklärt der Betreiber Vorlage nicht in gcc einen Anknüpfungs

Das funktioniert auch.

template class <T> 
class myClass 
{ 
    int myField; 

    // Helper function accessing my fields 
    void toString(std::ostream&) const; 

    // For some reason this requires using T, and not U as above 
    friend std::ostream& operator<<(std::ostream&, const myClass<T> &) 
    { 
     obj.toString(os); 
     return os; 
    } 
} 

Ich glaube, Sie können auch Vermeiden Sie Templating-Probleme, die Deklarationen in Headern erzwingen, wenn Sie eine übergeordnete Klasse verwenden, die den Operator < < nicht implementiert, und verwenden Sie eine virtuelle toString() - Methode.