Come sovraccaricare l'operatore ++ in due modi diversi per il suffisso a ++ e il prefisso ++ a?


Risposte:


165

Dovrebbe assomigliare a questo:

class Number 
{
    public:
        Number& operator++ ()     // prefix ++
        {
           // Do work on this.   (increment your object here)
           return *this;
        }

        // You want to make the ++ operator work like the standard operators
        // The simple way to do this is to implement postfix in terms of prefix.
        //
        Number  operator++ (int)  // postfix ++
        {
           Number result(*this);   // make a copy for result
           ++(*this);              // Now use the prefix version to do the work
           return result;          // return the copy (the old) value.
        }
}; 

15
Questo codice mostra anche la differenza di prestazioni tra prefisso e suffisso. Se l'oggetto che stai restituendo non si adatta a un registro della CPU, stai eseguendo una costosa operazione di copia. Questo va bene se devi usare il valore pre-incrementato, ma se non lo fai, postfix è molto meglio. Un esempio potrebbe essere un iteratore in cui di solito usi: for (pos = c.begin (); ...; ++ pos) {} invece di pos ++
Eric

22
@ Eric: l'hai corretto fino in fondo, a parte una frase nel mezzo in cui mescoli. Il suo prefisso è migliore.
Martin York

6
Perché Number operator++ (int)prende un intcome parametro anche se non lo usi?
Sean Letendre

10
@SeanLetendre: in realtà non accetta un parametro int. È un parametro falso. Ma i progettisti del linguaggio C ++ dovevano definire un modo per distinguere tra definizioni di funzioni di prefisso e suffisso. Questa è la decisione di progettazione che hanno preso.
Martin York

2
@EnricoMariaDeAngelis: La sintassi distingue i due. ++xè prefisso e quindi chiama operator++() while x++è postfisso e quindi chiamaoperator++(int)
Martin York

34

La differenza sta nella firma che scegli per il tuo sovraccarico operator ++.

Citato dall'articolo pertinente su questo argomento nelle domande frequenti su C ++ (vai lì per maggiori dettagli):

class Number {
  public:
    Number& operator++ ();     // prefix ++: no parameter, returns a reference
    Number  operator++ (int);  // postfix ++: dummy parameter, returns a value
};

PS: Quando l'ho scoperto, tutto ciò che ho visto inizialmente era il parametro fittizio, ma i diversi tipi di ritorno sono in realtà più interessanti; potrebbero spiegare perché ++xè considerato più efficiente che x++ in generale .


17

Hai due modi per sovraccaricare i due operatori (prefisso / suffisso) ++ per un tipo T:

Metodo oggetto:

Questo è il modo più semplice, utilizzando l'idioma OOP "comune".

class T
{
    public :
        T & operator++() // ++A
        {
            // Do increment of "this" value
            return *this ;
        }

        T operator++(int) // A++
        {
           T temp = *this ;
           // Do increment of "this" value
           return temp ;
        }
} ;

Funzione non membro dell'oggetto:

Questo è un altro modo per farlo: fintanto che le funzioni si trovano nello stesso spazio dei nomi dell'oggetto a cui si riferiscono, verranno prese in considerazione quando il compilatore cercherà una funzione da gestire ++t ;o t++ ;codice:

class T
{
    // etc.
} ;


T & operator++(T & p_oRight) // ++A
{
   // Do increment of p_oRight value
   return p_oRight ;
}

T operator++(T & p_oRight, int) // A++
{
   T oCopy ;
   // Copy p_oRight into oCopy
   // Do increment of p_oRight value
   return oCopy ;
}

È importante ricordare che, da un punto di vista C ++ (incluso un punto di vista del compilatore C ++), quelle funzioni non membri fanno ancora parte dell'interfaccia di T (fintanto che si trovano nello stesso spazio dei nomi).

Ci sono due potenziali vantaggi della notazione della funzione non membro:

  • Se riesci a codificarli senza renderli amici di T, allora hai aumentato l'incapsulamento di T
  • puoi applicarlo anche a classi o strutture di cui non possiedi il codice. Questo è un modo non intrusivo per migliorare l'interfaccia di un oggetto senza modificarne la dichiarazione.

1

Dichiara in questo modo:

class A
{
public:
    A& operator++();    //Prefix (++a)
    A operator++(int); //Postfix (a++)

};

Implementa correttamente: non scherzare con ciò che tutti sanno di fare (incrementa quindi usa, usa quindi incrementa).


-2

So che è tardi, ma ho avuto lo stesso problema e ho trovato una soluzione più semplice. Non fraintendetemi, questa è la stessa soluzione di quella in alto (pubblicata da Martin York). È solo un po ' più semplice. Solo un po. Ecco qui:

class Number
{
        public:

              /*prefix*/  
        Number& operator++ ()
        {
            /*Do stuff */
            return *this;
        }

            /*postfix*/
        Number& operator++ (int) 
        {
            ++(*this); //using the prefix operator from before
            return *this;
        }
};

La soluzione sopra è un po 'più semplice perché non utilizza un oggetto temporaneo nel metodo postfix.


6
Questo non è standard. L'operatore suffisso ++ dovrebbe restituire quello che era il valore prima dell'incremento, non dopo.
Kuilin Li

Questa risposta non è corretta. Il temporaneo è richiesto.
Rian Quinn
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.