C++ operator++()演算子について

C++には演算子のオーバーロードというものがある。
演算子とは + - * / = 等の変数や定数間で
計算等を行わせるために使う記号のこと

で,この演算子のオーバーロードとは,その + - * / = 等に
自分が新しく作った型(クラス)に対して,+ - * / = 等を
使ったときに,C++コンパイラはどういった処理を行わせるのか
わからないので,それをちゃんと動作できるようにする機能。
例:
class A
{
};

int main() 
{
   int x;
   x = 1+2; // これはC++コンパイラが分かる

   A a,b,c; // 自分で勝手に作った型 A
   a = b + c;  // これは型 Aに+を使っても,C++コンパイラには,何をしたらいいか分からない

   return 0;
}

これを,理解させるには,operator演算子を使い,演算子のオーバーロードを行います。
具体的には,こんな感じ

class A
{
};

A operator+(A& p1, A& p2)
{
   A ret; // ここにp1 と p2 を足し算する処理を記述します
   return ret;
}

int main() 
{
   A a,b,c; // 自分で勝手に作った型 A
   a = b + c;  //ここの + の処理は A operator+(A& p1, A& p2); の呼び出しを行う

   return 0;
}

------------------
さて,本題
A a;
++a;
これをしたいなら,

class A
{
public:
  A& operator++() {
    // ++ の処理
    return *this;
  }
};

でOKですが,しかし,

A a;
a++;
とすると,だめです・・・。なぜなら, ++a と a++は,ほとんど同じ動作なのですが
別の処理とみなされるからです。

これも使えるようにするには,

class A
{
public:
  A& operator++() {
    // ++ の処理
    return *this;
  }
  A& operator++(int ) {
    // ++ の処理
    return *this;
  }
};

という風に2つの operator++を用意しなければなりません。2つ目の operator++は
なんか変です。 引数に (int ) と付いています。
A a;
++a; // A& operator++() が使われる
a++; // A& operator++(int ) が使われる
とりあえず,動きます。

動作確認のためにoperatorの中で画面に出すように変更します。
#include <iostream>
using namespace std;

class A
{
public:
  A& operator++() {
    coutg <<  "++ の処理" << endl;
    return *this;
  }
  A& operator++(int ) {
    coutg <<  "++ の処理 int 付き" << endl;
    return *this;
  }
};

int main()
{
  A a;
  ++a;  // "++ の処理" が出力
  a++;  // "++ の処理 int 付き" が出力
  return 0:;
}

これで,動作確認が出来ます。 int付きが不要のコンパイラもあるかもしれません。
また,intの方を使うと,エラーになるかもしれません(コンパイラが古い場合)。

※そもそも,
#include <iostream>
でエラーが出る場合は,
#include <iostream.h>
と変更し, using namespace std; を省いてください。
ただし,この場合のコンパイラは相当古いので,新しいコンパイラの入手を
お勧めします


ここで,おわりではありません。
じゃあ,int付きのoperator++のintはいったい?
この引数のint値を確認してみましょう。

#include <iostream>
using namespace std;

class A
{
public:
  A& operator++() {
    coutg <<  "++ の処理" << endl;
    return *this;
  }
  A& operator++(int n) {
    coutg <<  "++ の処理 int 付き n =" << n << endl;
    return *this;
  }
};

int main()
{
  A a;
  ++a;  // "++ の処理" が出力
  a++;  // "++ の処理 int 付き n = ?" が出力
  return 0:;
}

これで見ることが出来ましたね。

この値を見れば,C++の設計上の無理の1つだといえることが分かります。

この値,意味がないのか?と思われそうですが,これに無理やり入れることが出来ます。

やり方は。。。



class A
{
public:
  A& operator++() {
    coutg <<  "++ の処理" << endl;
    return *this;
  }
  A& operator++(int n) {
    coutg <<  "++ の処理 int 付き n =" << n << endl;
    return *this;
  }
};

int main()
{
  A a;
  a.operator++();  // "++ の処理" が出力
  a.operator++(10);  // "++ の処理 int 付き n = 10" が出力
  return 0:;
}

という風に, operator++を直接呼び出す方法です。
まぁ,ここまでくると operatorの使い方が本末転倒な感じになるので,
普通は行わないでしょう(^^;



a++; としたとき,a.operator++(int n)が呼ばれて nの値がどうなるかは,自分で確認してね(^^

この記事へのコメント

hoge
2005年05月29日 14:05
そもそもなんで前置・後置で別々にオーバーロードできるようになっているかというとこのような違いを再現するためです。
int a = 0, b = 0;
cout << a++ << ++b << endl;
その趣旨から後置インクリメントのオーバーロードはこんな感じにする場合が多いのです。
//class A内
A operator++(int) {
A temp = *this;
++*this;
return temp;
}
ローカル変数を返すので参照を返さない(返せない)のです。
どうせならそこまで言及しましょうよ。

この記事へのトラックバック