2011-02-08 8 views
11

Così, dopo la ricerca in tutto il mondo per questo, non posso sembrare trovare come creare una classe di operatore di freccia, vale a dire,Come posso creare e utilizzare un operatore di classe arrow?

class Someclass 
{ 
    operator->() /* ? */ 
    { 
    } 
}; 

Ho solo bisogno di sapere come lavorare con esso e usarlo in modo appropriato. - quali sono i suoi input? - cosa restituisce? - Come si dichiara/prototipo correttamente?

+3

nessun input. Il tipo di restituzione dovrebbe essere un puntatore. Questo di solito viene usato per creare puntatori "intelligenti", quindi restituisce un puntatore all'oggetto avvolto. – Tim

risposta

14

L'operatore -> viene utilizzato per sovraccaricare member . Un piccolo esempio:

#include <iostream> 
struct A 
{ 
    void foo() {std::cout << "Hi" << std::endl;} 
}; 

struct B 
{ 
    A a; 
    A* operator->() { 
     return &a; 
    } 
}; 

int main() { 
    B b; 
    b->foo(); 
} 

Questo uscite:

Hi 
+0

l'operatore di freccia funziona anche per restituire i membri della struttura come fa i membri della classe? – Codesmith

+0

Può restituire membri della struct con la stessa facilità con cui può restituire i membri della classe. Quello che succede quando usi la freccia è determinato dal corpo dell'operatore ->() funzione membro. La riga "return & a;" può essere cambiato per restituire qualunque cosa tu decida sia appropriata. – Darryl

0

L'operatore "freccia" può essere sovraccaricato:

a->b 

sarà tradotto per

return_type my_class::operator->() 
+0

Non è così semplice, 'return_type {} ->() ->() ->() ... ->()' deve essere un puntatore perché questo sia un codice valido. – alfC

16

L'operatore freccia ha ingressi. Tecnicamente, può restituire quello che vuoi, ma dovrebbe restituire qualcosa che sia un puntatore o che possa diventare un puntatore through chained -> operators.

L'operatore -> dereferenziazioni automaticamente il suo valore di ritorno prima di chiamare il suo argomento utilizzando il built-in puntatore dereference, non operator*, quindi si potrebbe avere la seguente classe:

class PointerToString 
{ 
    string a; 

    public: 
    class PtPtS 
    { 
     public: 
     PtPtS(PointerToString &s) : r(s) {} 
     string* operator->() 
     { 
      std::cout << "indirect arrow"; 
      return &*r; 
     } 
     private: 
     PointerToString &r; 
    }; 

    PointerToString(const string &s) : a(s) {} 
    PtPts operator->() const 
    { 
     std::cout << "arrow dereference\n"; 
     return *this; 
    } 
    string &operator*() const 
    { 
     std::cout << "dereference\n"; 
     return a; 
    } 
}; 

utilizzarlo come:

PointerToString ptr(string("hello")); 
string::size_type size = ptr->size(); 

che viene convertito dal compilatore in:

string::size_type size = (*ptr.operator->().operator->()).size(); 

(con ben .operator->() se necessario per restituire un vero e proprio puntatore) e dovrebbe uscita

arrow dereference 
indirect dereference 
dereference 

Si noti, tuttavia, che è possibile effettuare le seguenti operazioni:

PointerToString::PtPtS ptr2 = ptr.operator->(); 

Da Stroupstrup:

La trasformazione dell'oggetto p nel puntatore p.operator->() non dipende dal membro m indicato. Questo è il senso in cui operator->() è un operatore postfisso unario. Tuttavia, non è stata introdotta una nuova sintassi, quindi è necessario un nome membro dopo lo ->

+0

Non c'è modo in cui questo codice venga compilato su un compilatore decente. –

+0

@SebastianRedl, sei corretto. Ho aggiornato la spiegazione e l'esempio in modo che venga compilato. –

Problemi correlati