ホーム » スタッフ » 斉藤徹 » 講義録 » オブジェクト指向 » 複素数クラスとC++の演算子オーバーロード

2025年4月
 12345
6789101112
13141516171819
20212223242526
27282930  

検索・リンク

複素数クラスとC++の演算子オーバーロード

複素数クラスの例

隠蔽化と基本的なオブジェクト指向の練習課題として、複素数クラスをあげる。ここでは、複素数の加算・乗算を例に説明をするので、減算・除算などの処理を記述することで、クラスの扱いに慣れてもらう。

直交座標系の複素数クラス

#include <stdio.h>
#include <math.h>

// 直交座標系の複素数クラス
class Complex {
private:
   double re ; // 実部
   double im ; // 虚部
public:
   void print() {
      printf( "%lf + j%lf¥n" , re , im ) ;
   }
   Complex( double r , double i )  // コンストラクタで要素の
     : re( r ) , im( i ) {         //  初期化はこのように書いてもいい
   }                               // re = r ; im = i ; の意味
   Complex()      // デフォルトコンストラクタ
     : re( 0.0 ) , im( 0.0 ) {
   }

   void add( Complex z ) {
      // 加算は、直交座標系だと極めてシンプル
      re = re + z.re ;
      im = im + z.im ;
   }
   void mul( Complex z ) {
      // 乗算は、直交座標系だと、ちょっと煩雑
      double r = re * z.re - im * z.im ;
      double i = re * z.im + im * z.re ;
      re = r ;
      im = i ;
   }
   double get_re() {
      return re ;
   }
   double get_im() {
      return im ;
   }
   double get_abs() { // 絶対値
      return sqrt( re*re + im*im ) ;
   }
   double get_arg() { // 偏角
      return atan2( im , re ) ;
   }
} ; // ←何度も繰り返すけど、ここのセミコロン忘れないでね
int main() {
   // 複素数を作る
   Complex a( 1.0 , 2.0 ) ;
   Complex b( 2.0 , 3.0 ) ;

   // 複素数の計算
   a.print() ;
   a.add( b ) ;
   a.print() ;
   a.mul( b ) ;
   a.print() ;

   return 0 ;
}

C++と演算子のオーバーロード

C++では、演算子のオーバーロードという機能がある。前の例では、複素数の計算で a.add( b ) といった呼び出しで 複素数の a + b の計算をして、計算結果が a に格納されていた。でもやっぱり、c = a + b ; と書けたらすごく便利。

ということで、C++ では、関数名を書く欄に、operator 演算子( 右辺 ) { … } という書き方ができる。

関数の返り値の前に inline を書くと、開いたサブルーチンにしてくれる。

仮引数宣言の const は、引数に対して修正が行われないことを示す。

型 関数名( 仮引数, … ) const { … } としてメソッドを定義すると、オブジェクトを書き換えないことを明示できる。

#include <stdio.h>
#include <math.h>

// 直交座標系の複素数クラス
class Complex {
private:
    double re ; // 実部
    double im ; // 虚部
public:
    Complex( double r , double i )  // コンストラクタで要素の
        : re( r ) , im( i ) {       //  初期化はこのように書いてもいい
    }                               // re = r ; im = i ; の意味
    Complex()      // デフォルトコンストラクタ
        : re( 0.0 ) , im( 0.0 ) {}

    // C++ではそのクラス専用の演算子を定義できる(演算子のオーバーロード)
    Complex operator+( const Complex &z ) const {
        // 加算は、直交座標系だと極めてシンプル
        return Complex( re + z.re , im + z.im ) ;
    }
    Complex operator*( const Complex &z ) const {
        // 乗算は、直交座標系だと、ちょっと煩雑
        double r = re * z.re - im * z.im ;
        double i = re * z.im + im * z.re ;
        return Complex( r , i ) ;
    }
    // getter メソッド
    inline double get_re()  const { return re ; }
    inline double get_im()  const { return im ; }
    double get_abs() const { return sqrt( re*re + im*im ) ; } // 絶対値
    double get_arg() const { return atan2( im , re ) ; }      // 偏角

    void print() {
        printf( "%lf + j%lf\n" , get_re() , get_im() ) ;
    }
    void print_polar() {
        printf( "%lf ∠ %lf\n" , get_abs() , get_arg() / 3.141592 * 180.0 ) ;
    }

    
} ; // ←何度も繰り返すけど、ここのセミコロン忘れないでね
int main() {
    // 複素数を作る
    Complex a( 1.0 , 2.0 ) ;
    Complex b( 2.0 , 3.0 ) ;
    
    // 複素数の計算
    Complex c = a + b ;
    Complex d = a * b ;
    // 結果の表示
    c.print() ;
    d.print() ;
    c.print_polar() ;
    d.print_polar() ;
    return 0 ;
}