質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

3回答

17087閲覧

C++ operatorの使い方がわかりません

ba_max009

総合スコア21

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2016/12/14 17:12

c++初心者です。
初歩的な質問なのかもしれませんが、調べてもよくわからず質問してしまいました。
operatorの意味や使い方についても教えていただけると幸いです。

よろしくお願いします><

###前提・実現したいこと
operatorをつかって複素数の計算を行いたいです。

###発生している問題・エラーメッセージ

1_7.cpp:10:40: error: ‘Complex Complex::operator-(Complex, Complex)’ must take either zero or one argument 1_7.cpp:15:41: error: ‘Complex Complex::operator*(Complex, Complex)’ must take either zero or one argument 1_7.cpp: In function ‘int main()’: 1_7.cpp:36:14: error: no match for ‘operator-’ in ‘c - b’ 1_7.cpp:38:14: error: no match for ‘operator*’ in ‘a * b’

###該当のソースコード

#include <iostream> class Complex{ private: double real; //実部 double imag; //虚部 public: Complex(){real=0.0; imag=0.0;} Complex(double r, double i){real=r; imag=i;} Complex operator-(Complex a,Complex b){ double r=a.re()-b.re(); double i=a.im()-b.im(); return Complex(r.i); } Complex operator*(Complex a, Complex b){ double r=a.re()*b.re(); double i=a.im()*b.im(); return Complex(r.i); } ~Complex(){} Complex(double r){real=r;imag=0;} double re() const{return real;} //実部を取り出す double im() const{return imag;} //虚部を取り出す void set_re(double r){real=r;} //実部を指定 void set_im(double i){imag=i;} //虚部を指定 void print(std::ostream& os) const{ //出力 os << real << "+" << imag << "i"; } }; int main(void){ Complex a(1.00, 2.00); Complex b(3.00, 4.00); Complex c(2.35, 5.32); Complex s=c-b; s.print(std::cout); std::cout << std::endl; Complex t=a*b; t.print(std::cout); std::cout << std::endl; return 0; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

iwanoteさん、naomi3さんの回答の補足的なコメントをさせてください。

  • Complex + Complexの演算子の定義

iwanoteさんの回答でもnaomi3さんの回答でもどちらでも定義できますが、自分は演算の対象がComplexのみなので、iwanoteさんの回答「メンバー関数として定義する」方がより自然に感じます。

  • double + Complexの演算子の定義

現在のコード上は定義されていませんが、このような演算を可能にするならComplexのメンバー関数として定義できません。よってnaomi3さんの方法が必要になります。
(naomi3さんは「フレンド関数にする」と説明されていますが、厳密には「グローバル関数にする」の方が適切と思います。理由は「フレンド関数にはグローバル関数と他クラスのメンバー関数の場合がある」こと、「グローバル関数から非公開メンバーにアクセスする必要がないならフレンドにする必要はない」ことの2点です。なおフレンド関数の意味は「あるクラスCのメンバーでない関数(グローバル関数 or 他クラスのメンバー関数)の中でCがfriendと宣言した関数のことで、その効果はCの非公開メンバーアクセスが可能な点」だと思います。「グローバル関数とメンバー関数の中間」という表現は意図はくみ取れますが少々不正確と思います。・・・細かい指摘でスミマセン)


蛇足:
本質問には直接関係しないのですが次のような点も課題として考えてみるとよいと思います。なおconstの方は難易度高めです(自分はC++学習の際苦労しました)

  • 性能的な配慮(引数の型をComplex -> const Complex&)
  • const Complexに対して演算子を使えるようにする

constを使わないのであれば気にしなくてもよいのですが使おうとすると現在の定義ではコンパイルエラーになります。

c++

1const Complex a(1.1, 2.2); // aは不変 2Complex b = a + a; // コンパイルエラー 3 4=>対処はクラスのメンバー関数の多くに及びます。以下は一部についてだけの対処例です。 5 6class Complex { 7 Complex operator+(Complex b) {} 8 -> 9 Complex operator+(const Complex& b) const {} 10};

複素数は標準ライブラリーに含まれているものの、自分で定義することでクラス定義、演算子定義、const、参照渡しの&など学べることが色々あるので良い題材だと思います。

投稿2016/12/15 03:45

編集2016/12/15 03:54
KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

operatorとは演算子のオーバーロード、つまり別の役割を与えるものです。
このプログラムは-の演算子を拡張するものとなっていると思います。
エラーの原因はこの書き方が悪いわけです。
operatorは演算子を拡張するわけですが、そのオペランドの個数は変えることができません。
この場合-はオペランドが二つです。
エラーを見るとmust take either zero or one argumentとなっています。
これを訳すと引数をひとつかふたつしか持てないということです。
暗黙的に一つ目のオペランドはthisポインタ、つまりそのクラス自身のポインタを渡しています。
つまりオペランドが一つ多いということです。
なのでoperator-(Complex b)としてa.~をthis->~と変更すれば大丈夫だと思います。

投稿2016/12/14 18:03

編集2016/12/14 18:03
iwanote

総合スコア295

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

operator- とoperator* にはfriendをつけて(メンバー関数とグローバル関数の中間のような)フレンド関数にしてください。フレンド関数はターゲットオブジェクトをthisで受け取る代わりに引数で受け取りたいときに使います。

operator*()は数学上の誤りがありましたので修正しました。

出力はprint()を使ってもできるのですが、operator-()と同じようにフレンド関数にすることで、
std::cout << 1.0 << std::endl;
と同じような記法で関数を呼び出せます。

C++

1friend Complex operator-(Complex a,Complex b){ 2 double r=a.re()-b.re(); 3 double i=a.im()-b.im(); 4 return Complex(r,i); 5} 6friend Complex operator*(Complex a, Complex b){ 7 double r=a.re()*b.re() - a.im()*b.im(); 8 double i=a.re()*b.im() + a.im()*b.re(); 9 return Complex(r,i); 10} 11 12friend std::ostream& operator<<(std::ostream& os, Complex c){ //出力 13 return os << c.re() << "+" << c.im() << "i"; 14} 15 16 Complex s=c-b; 17 std::cout << s << std::endl; 18 Complex t=a*b; 19 std::cout << t << std::endl; 20

投稿2016/12/14 21:52

naomi3

総合スコア1105

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2016/12/14 22:53

re(), im() がpublicなので friendである必要ないですね。
ozwk

2016/12/15 01:56

> フレンド関数はターゲットオブジェクトをthisで受け取る代わりに引数で受け取りたいときに使います。 friendってそういうことではないのでは
episteme

2016/12/15 03:45

そういうことではありません。 関数に対し「おまえはfriendだからprivate部に触れることを許す」てことです。
naomi3

2016/12/15 11:49

そうですね。言葉足らずですみませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問