2009-05-15 20 views
20

Sono nel processo di creazione di un elenco doppio-linked, e hanno sovraccaricato l'operatore = per fare in lista pari un'altra:Che cosa significa "operatore = deve essere un membro non statico"?

template<class T> 
void operator=(const list<T>& lst) 
{ 
    clear(); 
    copy(lst); 
    return; 
} 

ma ottengo questo errore quando provo a compilare:

container_def.h(74) : error C2801: 'operator =' must be a non-static member 

Inoltre, se è utile, la riga 74 è l'ultima riga della definizione, con "}".

+0

In che contesto si trova? classe? A livello superiore? – bdonlan

+2

Non ha davvero bisogno della lingua nella domanda nome poiché è anche codificata C++ –

+0

Questa domanda è ingannevole. La domanda [qui] (https://stackoverflow.com/questions/5037156/) è più interessante. Anche se la migliore formulazione sarebbe "Perché non posso operator = essere globale". La risposta di Johannes Schaub - litb lo chiarisce. –

risposta

17

Esattamente quello che dice: i sovraccarichi dell'operatore con 1 parametro devono essere funzioni membro. (Dichiarata all'interno della classe)

template<class T> 
void list<T>::operator=(const list<T>& rhs) 
{ 
    ... 
} 

Inoltre, è probabilmente una buona idea per restituire la LHS from = modo è possibile concatenare esso (come a = b = c) - in modo da rendere più list<T>& list<T>::operator=....

+1

Sì, ho appena realizzato: l'ho dichiarato nella classe, ma ho scritto "void operator =" invece di "lista void :: operator =" –

+13

Mi dispiace, ma questo è sbagliato. operator = deve essere un membro (come dice il compilatore). Lo stesso è vero per l'operatore [] e l'operatore() e forse alcuni altri mi mancano. Fondamentalmente tutti quelli che hanno a che fare con lo stato di modifica invece di produrre un valore. Correggi la tua risposta e ritirerò il -1. Il problema di Keand64 è stato che non ha specificato la classe (lista : :), che non ha molto a che fare con questa risposta. –

+0

Oh, oops. Scusa per questo>< –

6

Se si esegue l'overload di un operatore come una funzione membro, si dovrebbe utilizzare questo modello:

class A { 
    A& operator=(const A& other) { 
    if (this != &other) { 
     ... 
    } 
    return *this; 
    } 
} 

Tre cose da notare:

  1. Verificare l'autoassegnazione con l'operatore di assegnazione (come sopra);
  2. L'argomento deve essere un riferimento const; e
  3. Restituisce il risultato dell'operazione come riferimento non const in cui si restituisce * questo per consentire il concatenamento degli operatori.

È inoltre possibile sovraccaricare un operatore esterno alla classe. Questo non è rilevante per questo esempio perché non è possibile farlo con l'operatore di assegnazione, ma vale la pena notare perché in molti casi è superiore alle funzioni dei membri. La forma tipica è:

class A { 
    friend const A& operator+(const A& a, const A& b); 
    ... 
} 
const A& operator+(const A& a, const A& b) { 
    A& ret = ... 
    return ret; 
} 

Questo restituisce un riferimento const quindi non è possibile fare questo:

(a + b) = c 
+0

Davvero deve essere statico? No statico funziona bene per me in g ++. –

+0

Mi spiace farmi incrociare i fili. Le funzioni non comprese nelle classi sono statiche per impostazione predefinita. Puoi inserire la parola chiave statica ma non è necessaria, quindi non c'è differenza, quindi l'ho rimosso. – cletus

+0

l'operatore = deve essere un membro (lo stesso è vero per l'operatore []). Vorrei usare un altro esempio per mostrare il modo non membro. –

18

Metti che operatore all'interno della vostra definizione di classe. Deve essere un membro perché operator= è speciale e non si otterrebbe qualcosa scrivendolo comunque come non membro. Un operatore non membro ha due importanti vantaggi principali:

  • conversioni implicite del diritto e il lato sinistro dell'operatore invocazione
  • Non c'è bisogno di conoscere interni della classe. La funzione può essere realizzata come non-membro non-amico.

Per operator=, entrambi non sono utilizzabili. Assegnare a un risultato temporaneo di una conversione non ha senso, e nella maggior parte dei casi sarà necessario l'accesso a internals operator=. Inoltre, uno speciale operator= viene fornito automaticamente da C++ se non ne viene fornito uno (il cosiddetto operatore di copia-assegnazione). Rendere possibile sovraccaricare operator= come non membro avrebbe introdotto una complessità aggiuntiva per apparentemente nessun guadagno pratico, e quindi non è permesso.

Quindi modificare il codice in modo che assomiglia a questo (. Questo presuppone l'operator= è non un operatore di copia-assegnazione, ma assegnando da una list<T> a qualcos'altro Questo non è chiaro dalla tua domanda):

class MyClass { 
... 
    template<class T> 
    MyClass& operator=(const list<T>& lst) 
    { 
     clear(); 
     copy(lst); 
     return *this; 
    } 
... 
}; 

È piuttosto normale che uno operator= restituisca nuovamente un riferimento a se stesso. Ti raccomando di aderire a questa pratica. Sembrerà familiare ai programmatori e potrebbe causare sorprese se restituisse lo void all'improvviso.

-1

Da C++ standard, "Operatori binari":

"Un operatore binario sono attuati da una funzione membro non statica con un parametro o da una funzione non membro con due parametri"

Vuole che tu lo definisca in una classe, come membro, o lo renda un metodo statico (nel qual caso dovrebbe prendere due parametri (sia per lval che per rval)

+0

La domanda originale riguardava 'operator =', che non è (secondo lo standard C++) un "Operatore binario". Hai citato il paragrafo 13.5.2.1. Tuttavia, gli operatori di assegnazione sono discussi nella sezione 13.5.3: "Un operatore di assegnazione deve essere implementato da una funzione membro non statico con esattamente un parametro. ..." – mpb

Problemi correlati