Cpp 演算子のオーバーロード

提供:yonewiki

C++に戻る


本来の表記は「C++ クラス 演算子のオーバーロード」です。この記事に付けられた題名はテンプレート:記事名の制約から不正確なものとなっています。

※このページではC++にのみ存在する機能として、記事タイトルがC++ クラス 演算子のオーバーロードになっています。

クラス 演算子のオーバーロード

演算子のオーバーロードは、C++において特定の演算子に対してユーザー独自の挙動を定義する機能です。これにより、ユーザーは新しい型に対して組み込み型と同じように演算を行えるようになります。以下に、演算子のオーバーロードについて説明します。

演算子のオーバーロードの基本:

関数の定義:

演算子のオーバーロードは、特殊な形式のメンバ関数や非メンバ関数として定義されます。 メンバ関数の場合は、オペランドの左辺に対するオーバーロードが行われます。非メンバ関数の場合は、オーバーロード対象の型がオペランドの左辺または右辺にある場合に使用されます。


戻り値と引数:

オーバーロードされた演算子の関数は、その演算の結果として返り値を持ちます。 通常、二項演算子の場合、引数は少なくとも1つです。単項演算子の場合は1つの引数です。 引数の型や個数は演算子ごとに異なります。たとえば、+ 演算子は2項演算子であり、引数が2つ必要です。


オーバーロードの形式:

メンバ関数形式: ReturnType operator@(Parameters) const; (例: + 演算子の場合、T operator+(const T& rhs) const;) 非メンバ関数形式: ReturnType operator@(Parameters); (例: << 演算子の場合、std::ostream& operator<<(std::ostream& os, const T& obj);)


演算子のオーバーロードの例:

#include <iostream>

class Complex {
public:
    double real;
    double imag;

    // + 演算子のオーバーロード(メンバ関数形式)
    Complex operator+(const Complex& rhs) const {
        Complex result;
        result.real = real + rhs.real;
        result.imag = imag + rhs.imag;
        return result;
    }

    // << 演算子のオーバーロード(非メンバ関数形式)
    friend std::ostream& operator<<(std::ostream& os, const Complex& obj) {
        return os << "(" << obj.real << " + " << obj.imag << "i)";
    }
};

int main() {
    Complex a{1.0, 2.0};
    Complex b{3.0, 4.0};

    // + 演算子の使用
    Complex c = a + b;
    std::cout << "Result of addition: " << c << std::endl;

    return 0;
}


オーバーロード可能な演算子:

以下は、C++でオーバーロード可能な主要な演算子の一部です。これら以外にもいくつかの演算子がオーバーロード可能です。

算術演算子: +, -, *, /, % 比較演算子: ==, !=, <, >, <=, >= 論理演算子: &&, ||, ! 代入演算子: =, +=, -=, *=, /=, %= 単項演算子: +, -, ++, --, ! ビット演算子: &, |, ^, ~, <<, >> インデックス演算子: [] メンバアクセス演算子: -> 関数呼び出し演算子: ()

クラス 特殊な演算子のオーバーロード

 上記のような演算子オーバロードに付け加えて、複雑な引数指定方法になる演算子のオーバーロードを紹介します。


1.関数呼び出し演算子 ():

#include <iostream>

class Functor {
public:
    void operator()(int x) const {
        std::cout << "Function called with argument: " << x << std::endl;
    }
};

int main() {
    Functor functor;
    functor(42); // 関数呼び出し演算子がオーバーロードされたメソッドが呼ばれる
    return 0;
}


  • operator() が関数呼び出し演算子をオーバーロードしています。
  • オブジェクト functor を関数として呼び出すことができ、その結果として operator() が呼ばれます。


2. インデックス演算子 []:

#include <iostream>

class Array {
private:
    int values[5];

public:
    int& operator[](int index) {
        return values[index];
    }
};

int main() {
    Array arr;
    arr[2] = 42; // インデックス演算子がオーバーロードされたメソッドが呼ばれる
    std::cout << "Value at index 2: " << arr[2] << std::endl;
    return 0;
}


  • operator[] がインデックス演算子をオーバーロードしています。
  • オブジェクト arr を配列として扱い、arr[2] のように要素にアクセスできます。


3.メンバアクセス演算子 ->:

#include <iostream>

class SmartPointer {
private:
    int* data;

public:
    SmartPointer(int* ptr) : data(ptr) {}

    int operator*() const {
        return *data;
    }

    int* operator->() const {
        return data;
    }
};

int main() {
    int value = 42;
    SmartPointer sp(&value);
    std::cout << "Dereferenced value: " << *sp << std::endl;
    std::cout << "Pointer access value: " << sp->operator*() << std::endl; // 同じく operator-> が呼ばれる
    return 0;
}


  • operator-> がメンバアクセス演算子をオーバーロードしています。
  • SmartPointer オブジェクト sp をポインタのように扱え、sp-> の形でメンバにアクセスできます。

 

C++に戻る