Cosa vuol dire “operatore = deve essere un membro non statico”?

Sono in procinto di creare un elenco a doppio collegamento e ho sovraccaricato l’operatore = per fare in modo che nell’elenco sia uguale a un altro:

template void operator=(const list& 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 aiuta, la riga 74 è l’ultima riga della definizione, con “}”.

Esattamente quello che dice: i sovraccarichi dell’operatore con 1 parametro devono essere funzioni membro. (dichiarato all’interno della class)

 template void list::operator=(const list& rhs) { ... } 

Inoltre, probabilmente è una buona idea restituire il LHS da = in modo da poterlo concatenare (come a = b = c ) – quindi rendilo list& list::operator=....

Metti quell’operatore nella definizione della tua class. 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 lato destro e sinistro dell’invocazione dell’operatore
  • Non c’è bisogno di sapere sugli interni della class. La funzione può essere realizzata come non-membro non-amico.

Per operator= , entrambi non sono utilizzabili. Assegnare un risultato temporaneo di una conversione non ha senso, e l’ operator= avrà bisogno di accedere agli interni nella maggior parte dei casi. Inoltre, un operator= speciale operator= viene fornito automaticamente da C ++ se non ne viene fornito uno (il cosiddetto operatore di assegnazione delle copie). Rendendo ansible sovraccaricare l’ operator= come non membro avrebbe introdotto una complessità aggiuntiva per apparentemente nessun guadagno pratico, e quindi non è permesso.

Quindi cambia il tuo codice in modo che assomigli a questo (questo presuppone che l’ operator= non sia un operatore di assegnazione della copia, ma che assegni da una list a qualcos’altro. Questo non è chiaro dalla tua domanda):

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

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

Se sovraccarichi un operatore come funzione membro, dovresti 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 incaricato (come sopra);
  2. L’argomento dovrebbe 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.

Puoi anche sovraccaricare un operatore esterno alla class. Questo non è rilevante per questo esempio perché non è ansible 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 puoi farlo:

 (a + b) = c 

Da C ++ Standard, “Operatori binari”:

“Un operatore binario deve essere implementato da una funzione membro non statico con un parametro o da una funzione non membro con due parametri”

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