C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: 演算子のオーバーロード


(過去ログ 69 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■40284 / inTopicNo.1)  演算子のオーバーロード
  
□投稿者/ ひでき (1回)-(2009/08/23(Sun) 11:58:40)

分類:[C/C++] 

C++ 初心者です。演算子のオーバーロードの書き方がどうもわかりません。たとえば、次のようなプログラム(下手なプログラムですみません)で、

#include <iostream>
using namespace std;

class CCalc {
public:
CCalc (int val1) {
val = val1;
}
CCalc operator+(CCalc &calc) { // 単項演算子 + の定義
return val + calc.val * calc.val;
}
int val;
};

int main() {
CCalc objCalc(0);
CCalc objCalc1(7);
CCalc objCalc2(3);
objCalc = objCalc1 + objCalc2; // 演算子 + の計算
printf("value = %d\n", objCalc);
return 0;
}

「演算子 + の計算」式がどうしてこのように書けるのか理解できません。これを

objCalc = objCalc1.operator+(objCalc2); // 演算子 + の計算の別表記

と書きかえればわかるのですが、そうすると「単項演算子 + の定義」を呼び出しているのは、objCalc1 と objCalc2 のどちらなのでしょうか。また計算式を少し書き変えて、

CCalc objCalc3(2);
objCalc = objCalc1 + objCalc2 + objCalc3;

としても正常に作動します。これを「演算子 + の計算の別表記」で書き表すと、いったいどうなるでしょうか。用語などの使い方が間違っているかもしれません。よろしくご指導お願いします。
引用返信 編集キー/
■40286 / inTopicNo.2)  Re[1]: 演算子のオーバーロード
□投稿者/ επιστημη (2135回)-(2009/08/23(Sun) 12:12:15)
επιστημη さんの Web サイト
↓これ実行すりゃわかんでないかな。

#include <iostream>
#include <string>

using namespace std;

class CCalc {
  int cal;
  string name;
public:
  CCalc (const string& n, int v) : name(n), val(v) {}
  CCalc (int v) : name("un-named"), val(v) {}
  CCalc operator+(const CCalc &calc) {
    cout << name << "::operator+(" << calc.name << ")\n";
    return val + calc.val * calc.val;
  }
int val;
};

int main() {
  CCalc objCalc1("one",7);
  CCalc objCalc2("two", 3);
  CCalc objCalc3("three",9);
  cout << "case-1:\n";
  CCalc objCalc = objCalc1 + objCalc2;
  cout << "case-2:\n";
  objCalc = objCalc1 + objCalc2 + objCalc3;
  return 0;
}

引用返信 編集キー/
■40287 / inTopicNo.3)  Re[1]: 演算子のオーバーロード
□投稿者/ επιστημη (2136回)-(2009/08/23(Sun) 12:19:41)
επιστημη さんの Web サイト
> これを「演算子 + の計算の別表記」で書き表すと、いったいどうなるでしょうか。

"別の表記"って、↓コレのこと?

#include <iostream>
#include <string>

using namespace std;

class CCalc {
  int val;
  string name;
public:
  CCalc (const string& n, int v) : name(n), val(v) {}
  CCalc (int v) : name("un-named"), val(v) {}
  friend CCalc operator+(const CCalc& x, const CCalc& y) {
    cout << "operator+(" << x.name << ',' << y.name << ")\n";
    return CCalc(x.val+y.val);
  }
};

int main() {
  CCalc objCalc1("one",7);
  CCalc objCalc2("two", 3);
  CCalc objCalc3("three",9);
  cout << "case-1:\n";
  CCalc objCalc = objCalc1 + objCalc2;
  cout << "case-2:\n";
  objCalc = objCalc1 + objCalc2 + objCalc3;
  return 0;
}

引用返信 編集キー/
■40290 / inTopicNo.4)  Re[2]: 演算子のオーバーロード
□投稿者/ επιστημη (2137回)-(2009/08/23(Sun) 12:47:47)
επιστημη さんの Web サイト
No40286 ちょっちマチガイ。↓コッチが正解。

#include <iostream>
#include <string>

using namespace std;

class CCalc {
  int cal;
  string name;
public:
  CCalc (const string& n, int v) : name(n), val(v) {}
  CCalc (int v) : name("un-named"), val(v) {}
  CCalc operator+(const CCalc &calc) {
    cout << name << "::operator+(" << calc.name << ")\n";
    return val + calc.val * calc.val;
  }
};

int main() {
  CCalc objCalc1("one",7);
  CCalc objCalc2("two", 3);
  CCalc objCalc3("three",9);
  cout << "case-1:\n";
  CCalc objCalc = objCalc1 + objCalc2;
  cout << "case-2:\n";
  objCalc = objCalc1 + objCalc2 + objCalc3;
  return 0;
}

引用返信 編集キー/
■40293 / inTopicNo.5)  Re[3]: 演算子のオーバーロード
□投稿者/ ひでき (3回)-(2009/08/23(Sun) 13:37:03)
すばやい解答ありがとうございます。ただ、私には解答プログラムそのものが難解です。結論としては、どういうときも「演算子+」計算式の2番目の要素( objCalc2 )が呼び出し元になっているらしいことがわかります。どうしてそうなるのか、私にはよくわかりませんが…。

いただいたプログラムの中で、

CCalc (int v) : name("un-named"), val(v) {}

にマッチするものがあることがふしぎです。どのオブジェクトも文字列と整数の2つの引数をもっているはずなのにどうしてでしょうか(初心者にはこういうところがよくわからないんです)。

ところでお名前は「エピステーメー」さんというのですか(どういう意味?)。
引用返信 編集キー/
■40299 / inTopicNo.6)  Re[4]: 演算子のオーバーロード
□投稿者/ επιστημη (2138回)-(2009/08/23(Sun) 17:55:02)
επιστημη さんの Web サイト
> 結論としては、どういうときも「演算子+」計算式の2番目の要素( objCalc2 )が呼び出し元に
> なっているらしいことがわかります。どうしてそうなるのか、私にはよくわかりませんが…。

どうしてか、と訊かれると"それが規則だから"としか答えられないわけで ^^;

CCalc::operator+(CCalc) が定義されているなら
A + B は A.operator+(B) と解釈され、

operator+(CCalc,CCalc) が定義されているなら
A + B は operator+(A,B) と解釈されます。

> CCalc (int v) : name("un-named"), val(v) {}
>
> にマッチするものがあることがふしぎです。
> どのオブジェクトも文字列と整数の2つの引数をもっているはずなのにどうしてでしょうか

このコンストラクタで"intからCCalcを作るルールを追加してあげたから"です。

> ところでお名前は「エピステーメー」さんというのですか

です。先日パクられましたww → http://www.episteme-net.jp/

>(どういう意味?)。

http://www.episteme-net.jp/story/
だそうです。へー。

引用返信 編集キー/
■40302 / inTopicNo.7)  Re[1]: 演算子のオーバーロード
□投稿者/ ひでき (4回)-(2009/08/23(Sun) 19:49:54)
いろいろとありがとうございました。わかったことをまとめると、

1)演算子 + の呼び出し元は objCalc1 である。

これは
objCalc = objCalc1 + objCalc2;

objCalc = objCalc1.operator+(objCalc2);
と書き換えられることから明らか。つまり objCalc1 の下にある operator+ が objCalc3 を引数として計算し、その演算結果を objCalc に代入していると考えられます。

2)objCalc = objCalc1 + objCalc2 + objCalc3; は objCalc = objCalc1.operator+( objCalc2.operator+(objCalc3) ) と書き換えることができる。

これは 演算子 + が後ろから順に適用されるということです。つまり objCalc2 の下にある operator+ が objCalc3 を引数として計算した結果を、さらに引数として objCalc1 の下にある operator+ が演算するということです。

以上の結論は、「エピステーメー」さんともう一人の方(KYさん)からいただいた助言をもとに出しました。
解決済み
引用返信 編集キー/
■40306 / inTopicNo.8)  Re[2]: 演算子のオーバーロード
□投稿者/ επιστημη (2139回)-(2009/08/23(Sun) 21:37:32)
επιστημη さんの Web サイト
> これは 演算子 + が後ろから順に適用されるということです。

違います。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -