• ベストアンサー

メンバ関数のオーバーロード

#include <iostream> using namespace std; class Point{ private: int x; int y; public: Point(int a=0, int b=0){x=a; y=b;} Point operator+(Point p); }; Point Point::operator+(Point p) { Point tmp; tmp.x = x + p.x; //この部分    tmp.y = y + p.y; return tmp; } int main() { Point p1(1, 2); Point P2(3, 6); p1 = p1 + p2; } ------------- のtmp.x = x + p.x;がなぜこうなるのか解りません。 p1 + p2;をするための前処理?なのは解るのですが。

質問者が選んだベストアンサー

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.2

p1 + p2 が、p1.operator+(p2) として実行されるのは、sssoheiさんの言う通りです。 この時 Point::operator+ 関数には、p1 のアドレスが暗黙に渡され、自動的に用意された this という名のポインタ変数に格納されます。そして p2 の値は仮引数の Point p に渡されます。 関数内にメンバ名だけで存在する x や y は、この thisポインタを暗黙に使って参照されます。 つまり実際には、次のような処理をしているのです。(あくまでイメージです。) Point operator_plus(Point *this, Point p) {   Point tmp;   tmp.x = this->x + p.x;  /* p1のxメンバとp2のxメンバを足す */   tmp.y = this->y + p.y;  /* p1のyメンバとp2のyメンバを足す */   return tmp; }   : p1 = operator_plus(&p1, p2); 結局それぞれのメンバ同士の足し算を行うわけですが、足し算結果は Point型でなければならないので、tmp という一時的に結果を格納する変数を作って、それを戻値として返すわけです。 質問されていることと違いましたら、補足をお願いします。

yosiyosi
質問者

お礼

理解できました。ありがとうございました。

その他の回答 (1)

  • sssohei
  • ベストアンサー率33% (33/98)
回答No.1

「メンバ関数のオーバーロード」ではなく「演算子のオーバーロード」じゃないでしょうか^^; たしか「p1 = p1 + p2;」というのは「p1 = p1.operator+(p2);」と言うように計算はずです。つまり、コンパイラが演算子を関数に読み替えているわけです。 # ちょっと怪しいです…^^; そのようになっていることで、スムーズに問題が解決出来るわけです。 # 「p1 = p1 + p2 + p3;」であれば「p1 = p1.operator+(p2.operator+(p3));」という感じに あと「return tmp;」というのは「tmp」のコピーを返しています。この様に、直接書き換えないのは「p1 = p2 + p3;」の様な時を考えてみてください。納得出来なかったら補足をお願いします。 EffectiveC++という良書(と評判です。私もそう思います)がありますので、良ければ読んでみてください。 # この項目は扱われていませんのであしからず^^;

yosiyosi
質問者

お礼

ありがとうございました。本読んで見ます。

関連するQ&A

  • +演算子オーバーロード

    こんにちは。お世話になっております。 // +演算子オーバーロード CPoint CPoint::operator+(CPoint& obj) //~(1) { CPoint tmp; tmp.m_x = m_x + obj.m_x; tmp.m_y = m_y + obj.m_y; return tmp; } int main() { CPoint point1( 100, 150 ); CPoint point2( 200, 50 ); std::cout << "x:" << point1.getx() << "y:" << point1.gety() << std::endl; point1 = point1 + point2; // オーバーロードされた+演算子が呼び出される std::cout << "x:" << point1.getx() << "y:" << point1.gety() << std::endl; point1 += point2; // オーバーロードされた+=演算子が呼び出される std::cout << "x:" << point1.getx() << "y:" << point1.gety() << std::endl; return 0; } 某サイトで上のようなサンプルプログラムがあるのですが これはc++で書かれた「+演算子オーバーロード」の定義で、動作としては 「point1 = point1.operator+( point2 ); // point1 = point1 + point2; と同じ」というような動作です。 それで疑問が出てきたのですが、イコールの右側で足す数が↓のような3つの場合、ans = a + b + c;です。 これだと(1)のところの引数を2つをとる関数を別に作らないとだめでしょうか?それとも、ans = ((a + b) + c);というふうに優先順位で自動的に計算してくれる+演算子オーバーロードのプログラムを教えてくれませんか?↑式のカッコは便宜上付けただけで、出来ればans = a + b + c;だけで計算出来るプログラムを教えてください。

  • str メンバ関数について

    str メンバ関数について 下記のstring Date::to_string() const のstr()メンバ関数が日付クラスDate、 (インタフエース部、実装部)に定義等が記入されていないので、何処に定義されているか教えてください。 ************************************************************* // 日付クラスDate(第2版:実装部) #include <ctime> #include <sstream> #include <iostream> #include "Date.h" using namespace std; //--- 文字列表現を返却 ---// string Date::to_string() const { ostringstream s; s << year << "年" << month << "月" << day << "日"; return s.str(); } ****************************************************************** // 日付クラスDate(第2版:インタフェース部) #include <string> #include <iostream> using namespace std; class Date { int year; // 西暦年 int month; // 月 int day; // 日 public: Date(); // デフォルトコンストラクタ Date(int y, int m = 1, int d = 1); // コンストラクタ int Year() const { return year; } // 年を返却 int Month() const { return month; } // 月を返却 int Day() const { return day; } // 日を返却 string to_string() const; // 文字列表現を返却 }; ostream& operator<<(ostream& s, const Date& x); // 挿入子

  • 添字演算子

    #include <iostream> class hoge{ private: int a; public: hoge(){ a = 0; } int operator+(int fuga){ a = a + fuga; return a; } int operator[](int fuga){ return 1; } }; int main(){ hoge* p; p = new hoge; std::cout << ((*p) + 5) << std::endl; std::cout << ((*p)[1] ) << std::endl; // 5 // 1 // std::cout << ((*p) [] 1); エラーです。何故ですか? }

  • 関数名、パラメータは同じで、戻り値によって異なる処理?

    戻り値というより、受け側によって関数の振る舞いを変えたいのですが、 C++では、同名、同パラメータはC2556のコンパイルエラーになります。 Perlでいうリスト値を返すかスカラー値を返すかは呼び出し側によるようなことをしたいのですが、C++では無理でしょうか? 下の例では、//...部分は戻り値によって異なるのでC++のテンプレート?では無理そうですが、そんなことはC++でできるのでしょうか? 似たようなテクニックでも構いませんので、知識の豊富な方、教えてください。 #include <iostream> #include <string> using namespace std; class A { public: A(){} ~A(){} int test(int x, int y){           //... return 0; } string test(int x, int y){ // ... return ""; } }; void main(void){ A a; int ret1 = a.test(1,2); string ret2 = a.test(1,2); cout << endl << "End..." << endl; }

  • 参照について

    C++初心者です。 #include <iostream> using namespace std; class Foo{ public: Foo() {;} Foo(const Foo&) {cout<< "A ";} Foo& operator = (const Foo&){cout << "B "; return *this;}   ←← }; int main(){ Foo x; x = Foo(); return 0; } において←←の部分を上記のようにFoo& operatorにした場合には 出力が"B"となりFoo operatorにした場合には出力が"B A"になりました。&がある場合と無い場合でどのようなことが起こっているのかよく分からないのですが教えて頂けないでしょうか? よろしくお願いします。

  • 関数呼び出しについて

    今cygwin 上でC++の勉強をしているのですが 以下の2つのプログラムの違いがよくわかりません どなたかよろしくお願いします <プログラム1> #include<iostream> using namespace std; int a(); int main(){ cout << abs();  return 0;} int a(){ cout << "test\n";  return 1;} <プログラム2> #include<iostream> using namespace std; int a(int i); int main(){ cout << a(1);  return 0;} int a(int i){ cout << "test\n";  return i;} プログラム1では関数a()内の"test"が出力されるのですが プログラム2ではa(int i)内の"test"は出力されません。 この違いはどこにあるのでしょうか? 同じプログラムでint a() と int a(int i)を double a() と double a(double d)にすると この違いは生じません。なぜaの戻り値をint に設定したときだけ この違いが生じるのでしょうか?

  • 【C++】0保証の有無

    Cの開発経験のみで、C++に関しては初心者です。 下記のサンプルコードで、main()関数にてobj1.xとobj2.y の初期値設定をしているのですが、 obj1.yとobj2.xに関しては何も設定していません。 obj2.xはobj1.xの値をコピーしているので問題ないと思いますが、 obj1.yは不定な値をインクリメントする事には ならない(0保証される)のでしょうか? (出力結果を見ると、0が入っていたと認識できるんですが、 結果論で片付けるのはイヤなので・・・) 以下、サンプルコード ---------------------------------- #include<iostream> using namespace std; class POINT { public: long x; long y; void operator ++(int n) { x++; y++; } POINT operator ++() { ++x; ++y; return *this; } } obj1 , obj2 ; int main() { obj1.x = 10; obj2.y = 5; obj2 = ++obj1; obj2++; cout << "x = " << obj1.x << "\ty = " << obj1.y << '\n'; cout << "x = " << obj2.x << "\ty = " << obj2.y << '\n'; return 0; } ----------------------------

  • 変数の宣言、初期化

    C++を習い始めたばかりの初心者です。下のプログラムを教えてください。 2つの整数値をキーボードから入力し、それをint型変数xとyに格納する。 一方double型変数aとbをそれぞれ5.3と2.5で初期化する。 このときa*x+b*yを算出し出力するプログラムを作成せよ。 本当に始めたばかりなので見当違いなことを書いてるかもしれませんが 自分でやってみるとこんなふうになりました。 #include <iostream> using namespace std; int main() { int x,y; cin>>x>>y;  ←キーボードで入力する。 int a(5.3);  ←初期化 int b(2.5); x=double(a);  ←キャスト y=double(b); cout<<a*x+b*y<<endl; return 0; } お願いします。

  • constのついたメンバ関数

     こんにちは。 C++を勉強しているのですが疑問に思ったことがあります。 const指定したメンバ関数にメンバ変数の変更をすることはエラーになるはずなんですが、 下記にある(*m_pRefCnt)++; はコンパイルが通るようです。 なぜこの一文だけ通るのでしょうか? 以下にソースを添付しておきます。 #include <iostream> class hogeClass { private: int* m_pRefCnt; int val; void AddRef() const { (*m_pRefCnt)++; // これはOK? val = 100; // これは駄目 } void Release() { } public: explicit hogeClass(char* src = NULL) : val(0) { } int& GetRefCnt() { return *(m_pRefCnt); } virtual ~hogeClass() { Release(); } }; int main() { int c = 435, k = 222; using namespace std; hogeClass a; getchar(); return 0; } 分かる人がいたらよろしくお願いします。

  • 合計値を求める関数

    #include<iostream> using namespace std; //sum関数の定義 int sum(int x, int y) { return x + y;  } int main() { int num1, num2, ans; cout << "1番目の整数を入力して下さい。\n"; cin >> num1; cout << "2番目の整数値を入力して下さい。\n"; cin >> num2; ans = sum(num1, num2); cout << "合計は" << ans << "です。\n"; return 0; }  ここのreturn x+y;の所の合計値を戻り値として返す処理の仕組みを解りやすく教えて欲しいです、戻り値はちょっと解りづらいです、よろしくお願いします。