接尾辞a ++と接頭辞++ aの2つの異なる方法でoperator ++をオーバーロードする方法は?


回答:


165

次のようになります。

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
このコードは、プレフィックスとポストフィックスのパフォーマンスの違いも示しています。返すオブジェクトがCPUレジスターに収まらない場合は、コストのかかるコピー操作を行っています。プリインクリメントされた値を使用する必要がある場合はこれで問題ありませんが、使用しない場合は、postfixの方がはるかに優れています。たとえば、通常使用するイテレータは次のようになります:for(pos = c.begin(); ...; ++ pos){} pos ++ではなく{}
Eric

22
@エリック:あなたはそれがあなたが混ぜる真ん中の文章を除いて、ずっと正しいです。より良いプレフィックス。
マーティンヨーク

6
使用しないのにNumber operator++ (int)、なぜをintパラメーターとして取るのですか?
Sean Letendre 2017

10
@SeanLetendre:実際にはintパラメータを取りません。その偽のパラメータです。しかし、C ++言語の設計者は、前置関数定義と後置関数定義を区別する方法を定義する必要がありました。これは、彼らが行った設計上の決定です。
マーティンヨーク

2
@EnricoMariaDeAngelis:構文は2つを区別します。++xはプレフィックスであり、したがってコールされますがoperator++()x++はポストフィックスであり、コールされますoperator++(int)
Martin York

34

違いは、のオーバーロードに対して選択する署名にありますoperator ++

C ++ FAQのこの主題に関する関連記事から引用(詳細はこちらを参照):

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

PS:これについて知ったとき、最初に見たのはダミーパラメータだけでしたが、実際にはさまざまな戻り値の型の方が興味深いものです。彼らはなぜ一般++xよりも効率的であると考えられるかを説明するかもしれません。x++


17

タイプTの2つの(前置/後置)++演算子をオーバーロードする方法は2つあります。

オブジェクトメソッド:

これは、「一般的な」OOPイディオムを使用する最も簡単な方法です。

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

オブジェクトの非メンバー関数:

これはもう1つの方法です。関数が参照しているオブジェクトと同じ名前空間にある限り、コンパイラが処理++t ;またはt++ ;コーディングする機能を検索するときに、これらの機能が考慮されます。

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

C ++の観点(C ++コンパイラの観点を含む)から見ると、これらの非メンバー関数は(同じ名前空間にある限り)Tのインターフェイスの一部であることに注意してください。

非メンバー関数表記には2つの潜在的な利点があります。

  • それらをTのフレンドにせずにそれらをコーディングすることに成功した場合は、Tのカプセル化を増やします。
  • これは、コードを所有していないクラスまたは構造体にも適用できます。これは、オブジェクトの宣言を変更せずにオブジェクトのインターフェースを拡張する、邪魔にならない方法です。

1

次のように宣言します。

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

};

適切に実装する-誰もが知っていることを台無しにしないでください(増分してから使用し、使用してから増分します)。


-2

遅いことはわかっていますが、同じ問題があり、より簡単な解決策が見つかりました。誤解しないでください。これは(Martin Yorkが投稿した)一番上のソリューションと同じです。それは少し簡単です。ちょっとだけ。ここにあります:

class Number
{
        public:

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

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

上記のソリューションは、postfixメソッドで一時オブジェクトを使用しないため、少し単純です。


6
これは標準ではありません。postfix operator ++は、インクリメント後ではなく、インクリメント前の値を返す必要があります。
Kuilin Li 2018

この答えは間違っています。一時は必須です。
Rian Quinn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.