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

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

ただいまの
回答率

90.46%

  • C++

    4552questions

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

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

受付中

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 4,860

ba_max009

score 15

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 foroperator-’ in ‘c - b’
1_7.cpp:38:14: error: no match foroperator*’ 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;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+1

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

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を使わないのであれば気にしなくてもよいのですが使おうとすると現在の定義ではコンパイルエラーになります。
const Complex a(1.1, 2.2); // aは不変
Complex b = a + a; // コンパイルエラー

=>対処はクラスのメンバー関数の多くに及びます。以下は一部についてだけの対処例です。

class Complex {
  Complex operator+(Complex b) {}
  ->
  Complex operator+(const Complex& b) const {}
};

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

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

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

friend Complex operator-(Complex a,Complex b){
    double r=a.re()-b.re();
    double i=a.im()-b.im();
    return Complex(r,i);
}
friend Complex operator*(Complex a, Complex b){
    double r=a.re()*b.re() - a.im()*b.im();
    double i=a.re()*b.im() + a.im()*b.re();
    return Complex(r,i);
}

friend std::ostream& operator<<(std::ostream& os, Complex c){ //出力
    return os << c.re() << "+" << c.im() << "i";
}

    Complex s=c-b;
    std::cout << s << std::endl;
    Complex t=a*b;
    std::cout << t << std::endl;

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/15 07:53

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

    キャンセル

  • 2016/12/15 10:56

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

    friendってそういうことではないのでは

    キャンセル

  • 2016/12/15 12:45

    そういうことではありません。

    関数に対し「おまえはfriendだからprivate部に触れることを許す」てことです。

    キャンセル

  • 2016/12/15 20:49

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

    キャンセル

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

  • ただいまの回答率 90.46%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C++

    4552questions

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