Operatör ++ 'yı postfix a ++ ve önek ++ a için iki farklı şekilde nasıl aşırı yükleyebilirim?


Yanıtlar:


165

Şöyle görünmeli:

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
Bu kod aynı zamanda önek ve sonek performans farkını da gösterir. Döndüğünüz nesne bir CPU kaydına uymuyorsa, pahalı bir kopyalama işlemi yapıyorsunuz demektir. Önceden artırılmış değeri kullanmanız gerekiyorsa bu sorun değildir, ancak kullanmazsanız, postfix çok daha iyidir. Örneğin, pos ++ yerine for (pos = c.begin (); ...; ++ pos) {}
Eric

22
@Eric: Karıştırdığın ortadaki bir cümle dışında tamamen düzeltmişsin. Öneki daha iyi.
Martin York

6
Neden gelmez Number operator++ (int)bir alacak intbunu kullanmasanız dahi olsa bir parametre olarak?
Sean Letendre

10
@SeanLetendre: Aslında bir int parametresi almıyor. Sahte bir parametredir. Ancak C ++ dilinin tasarımcıları, önek ve sonek işlev tanımlarını ayırt etmek için bir yol tanımlamalıydı. Verdikleri tasarım kararı bu.
Martin York

2
@EnricoMariaDeAngelis: Sözdizimi ikisini birbirinden ayırır. ++xönektir ve bu nedenle sonek operator++() iken çağırır x++ve bu nedenle çağırıroperator++(int)
Martin York

34

Aradaki fark, aşırı yükleriniz için hangi imzayı seçtiğinizde yatmaktadır. operator ++ .

C ++ SSS'de bu konuyla ilgili makaleden alıntılanmıştır (daha fazla ayrıntı için oraya gidin):

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

Not: Bunu öğrendiğimde, başlangıçta gördüğüm tek şey kukla parametresiydi, ancak farklı dönüş türleri aslında daha ilginç; neden onlar açıklayabilir ++xdaha verimlidir olarak kabul edilir x++ genelde .


17

T türü için iki (önek / sonek) ++ işlecini aşırı yüklemenin iki yolu vardır:

Nesne yöntemi:

Bu, "yaygın" OOP deyimini kullanmanın en kolay yoludur.

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

Üye olmayan nesne işlevi:

Bu, bunu yapmanın başka bir yoludur: İşlevler, başvurdukları nesneyle aynı ad alanında olduğu sürece, derleyici işlenecek bir yazı tipi ++t ;veya t++ ;kod aradığında dikkate alınacaktır :

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

Bir C ++ bakış açısından (bir C ++ derleyici bakış açısı dahil), üye olmayan bu işlevlerin hala T'nin arayüzünün bir parçası olduğunu (aynı ad alanında oldukları sürece) hatırlamak önemlidir.

Üye olmayan işlev gösteriminin iki olası avantajı vardır:

  • Onları T'nin arkadaşı yapmadan kodlamayı başarırsanız, T'nin kapsüllenmesini artırmış olursunuz.
  • bunu koduna sahip olmadığınız sınıflara veya yapılara bile uygulayabilirsiniz. Bu, bildirimini değiştirmeden bir nesnenin arayüzünü geliştirmenin müdahaleci olmayan bir yoludur.

1

Şöyle beyan edin:

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

};

Doğru şekilde uygulayın - herkesin yaptığını bildiği şeylerle uğraşmayın (artırın sonra kullanın, kullanın sonra artırın).


-2

Geç olduğunu biliyorum ama aynı sorunu yaşadım ve daha basit bir çözüm buldum. Beni yanlış anlamayın, bu en iyiyle aynı çözüm (Martin York tarafından yayınlanmıştır). Sadece biraz daha basit. Birazcık. İşte burada:

class Number
{
        public:

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

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

Yukarıdaki çözüm biraz daha basittir çünkü postfix yönteminde geçici bir nesne kullanmaz.


6
Bu standart değil. Sonek operatörü ++, değerin artmadan önce ne olduğunu döndürmelidir, sonra değil.
Kuilin Li

Bu cevap yanlıştır. Geçici gerekli.
Rian Quinn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.