Bagaimana cara membebani operator ++ dengan dua cara berbeda untuk postfix a ++ dan prefix ++ a?

Jawaban:

165

Akan terlihat seperti ini:

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.
        }
}; 
Martin York
sumber
15
Kode ini juga menunjukkan perbedaan kinerja prefiks vs. postfix. Jika objek yang Anda kembalikan tidak cocok dengan register CPU, Anda sedang melakukan operasi penyalinan yang mahal. Ini bagus jika Anda perlu menggunakan nilai pre-incremented, tetapi jika tidak, postfix jauh lebih baik. Contohnya adalah iterator di mana Anda biasanya menggunakan: for (pos = c.begin (); ...; ++ pos) {} alih-alih pos ++
Eric
22
@ Eric: Anda sudah benar sepenuhnya terlepas dari kalimat di tengah tempat Anda mencampur. Awalannya lebih baik.
Martin York
6
Mengapa Number operator++ (int)mengambil intsebagai parameter meskipun Anda tidak menggunakannya?
Sean Letendre
10
@SeanLetendre: Ini tidak benar-benar mengambil parameter int. Ini adalah parameter palsu. Tetapi perancang bahasa C ++ harus mendefinisikan cara untuk membedakan antara definisi fungsi prefiks dan postfix. Ini adalah keputusan desain yang mereka buat.
Martin York
2
@EnricoMariaDeAngelis: Sintaksnya membedakan keduanya. ++xadalah prefiks dan dengan demikian memanggil operator++() while x++adalah postfix dan dengan demikian memanggiloperator++(int)
Martin York
34

Perbedaannya terletak pada tanda tangan yang Anda pilih untuk kelebihan beban Anda operator ++.

Dikutip dari artikel yang relevan tentang subjek ini di C ++ FAQ (buka sana untuk lebih jelasnya):

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

PS: Ketika saya mengetahui tentang ini, yang saya lihat awalnya hanyalah parameter dummy, tetapi tipe pengembalian yang berbeda sebenarnya lebih menarik; mereka mungkin menjelaskan mengapa ++xdianggap lebih efisien daripada x++ secara umum .

stakx - tidak lagi berkontribusi
sumber
17

Anda memiliki dua cara untuk membebani dua operator (prefix / postfix) ++ untuk tipe T:

Metode objek:

Ini adalah cara termudah, menggunakan idiom OOP "umum".

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 ;
        }
} ;

Objek fungsi non-anggota:

Ini adalah cara lain untuk melakukannya: Selama fungsi berada di namespace yang sama dengan objek yang dirujuknya juga, fungsi tersebut akan dipertimbangkan saat kompilator akan mencari fonction untuk ditangani ++t ;atau t++ ;dikodekan:

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 ;
}

Penting untuk diingat bahwa, dari sudut pandang C ++ (termasuk sudut pandang compiler C ++), fungsi-fungsi non-anggota tersebut masih merupakan bagian dari antarmuka T (selama mereka berada di namespace yang sama).

Ada dua keuntungan potensial dari notasi fungsi non-anggota:

  • Jika Anda berhasil mengkodekannya tanpa menjadikannya teman T, maka Anda meningkatkan enkapsulasi T
  • Anda dapat menerapkan ini bahkan ke kelas atau struktur yang kodenya tidak Anda miliki. Ini adalah cara non-intrusif untuk meningkatkan antarmuka objek tanpa mengubah deklarasinya.
paercebal.dll
sumber
1

Nyatakan seperti ini:

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

};

Implementasikan dengan benar - jangan mengacaukan apa yang semua orang tahu bahwa mereka lakukan (kenaikan lalu gunakan, gunakan lalu selisih).

Kate Gregory
sumber
-2

Saya tahu ini terlambat, tetapi saya memiliki masalah yang sama dan menemukan solusi yang lebih sederhana. Jangan salah paham, ini adalah solusi yang sama dengan yang teratas (diposting oleh Martin York). Ini hanya sedikit lebih sederhana. Hanya sedikit. Ini dia:

class Number
{
        public:

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

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

Solusi di atas sedikit lebih sederhana karena tidak menggunakan objek sementara dalam metode postfix.

X. Mora
sumber
6
Ini tidak standar. Operator postfix ++ harus mengembalikan nilai sebelum incrementing, bukan setelahnya.
Kuilin Li
Jawaban ini salah. Sementara itu diperlukan.
Rian Quinn