C++演算子オーバーロード:コード例付き実践ガイド
演算子オーバーロードとは
C++で演算子オーバーロードを使用すると、同じスコープ内で1つの演算子に複数の意味を割り当てられます。目的は、ユーザー定義型に対して演算子にカスタム動作を与えることです。
演算子オーバーロードにより、ほとんどのC++演算子を再定義し、1つの記号で異なる操作を実行できるようになります。
このチュートリアルで学ぶ内容:
- 演算子オーバーロードとは
- 構文
- C++での演算子オーバーロードの異なるアプローチ
- オーバーロードできない演算子
- 重要な考慮事項
- 演算子オーバーロードのルール
- 演算子をオーバーロードする実践方法
構文
C++演算子をオーバーロードするには、クラス内部で特殊なメンバ関数を以下のように定義します:
class class_name {
...
public:
return_type operator symbol (argument(s)) {
...
}
...
};
構成要素:
- return_type – 演算子関数が返す型
- operator – 宣言を開始するキーワード
- symbol – オーバーロードしたい演算子(例:
+、-、<、++) - argument(s) – パラメータ、通常の関数と同様
例1:
#include <iostream>
using namespace std;
class TestClass {
private:
int count;
public:
TestClass() : count(5) {}
void operator --() {
count = count - 3;
}
void Display() {
cout << "Count: " << count;
}
};
int main() {
TestClass tc;
--tc;
tc.Display();
return 0;
}
出力:
コードのスクリーンショット:
コード解説:
- 入出力機能のため
<iostream>をインクルード - 簡潔さのため
std名前空間を使用 TestClassクラスを定義countをプライベートデータメンバにcountを5で初期化するパブリックコンストラクタを提供- 前置
--演算子をオーバーロードし、countから3を減算 - 現在値を出力する
Display()を実装 main()でインスタンス作成、オーバーロード演算子適用、結果表示
C++での演算子オーバーロードの異なるアプローチ
オーバーロードは以下で実現可能:
- メンバ関数
- 非メンバ関数(フレンド関数またはフリー関数)
- フレンド関数(プライベートデータアクセスが必要な場合)
- 左オペランドがクラスのオブジェクトなら、通常メンバ関数を使用
- 左オペランドが異なる型なら、非メンバ関数が必要
- フレンド関数は、演算子がプライベート/プロテクトメンバにアクセスする必要がある場合に有用
すべてのC++演算子をオーバーロードできるか?
いいえ。以下の演算子はオーバーロード不可です:
::– スコープ解決?:– 三項条件.– メンバーアクセスsizeof– サイズ照会*(メンバポインタセレクタ)
覚えておくべきこと
- オーバーロードはユーザー定義型のみに影響;組み込み型は元の動作を保持
- 代入(
=)とアドレス取得(&)演算子は、コピーコンストラクタや代入演算子を提供するクラスで自動的にオーバーロードされる - 演算子の優先順位は変更されない;評価順序を強制するには括弧を使用
- 3つの演算子—
::、.、?:—は明示的にオーバーロード禁止
演算子オーバーロードのルール
- 少なくとも1つのオペランドがユーザー定義クラス型でなければならない
- 既存の演算子のみオーバーロード可能;新しい演算子記号を導入不可
- 一部の演算子(
new、deleteなど)はフレンド関数としてオーバーロード不可だが、メンバ関数としては可能
演算子をオーバーロードする方法
例1:インクリメント演算子
#include <iostream>
using namespace std;
class OperatorOverload {
private:
int x;
public:
OperatorOverload() : x(10) {}
void operator ++() {
x += 2;
}
void Print() {
cout << "The Count is: " << x;
}
};
int main() {
OperatorOverload ov;
++ov;
ov.Print();
return 0;
}
出力:
コードのスクリーンショット:
コード解説:
<iostream>をインクルードしstd名前空間を使用- プライベート
int xを持つOperatorOverloadクラスを定義 - コンストラクタで
xを10で初期化 - 前置
++演算子をオーバーロードし、xに2を加算 - 更新値を表示する
Print()を実装 main()でオブジェクト作成、オーバーロード演算子呼び出し、結果出力
例2:複素数の加算
#include <iostream>
using namespace std;
class TestClass {
private:
int real, over;
public:
TestClass(int rl = 0, int ov = 0) : real(rl), over(ov) {}
TestClass operator + (TestClass const &obj) {
TestClass result;
result.real = real + obj.real;
result.over = over + obj.over;
return result;
}
void print() {
cout << real << " + i" << over << endl;
}
};
int main() {
TestClass c1(9, 5), c2(4, 3);
TestClass c3 = c1 + c2;
c3.print();
}
出力:
コードのスクリーンショット:
コード解説:
<iostream>をインクルードしstd名前空間を使用realとoverコンポーネントを持つTestClassを定義- 初期化用コンストラクタを提供
+演算子をオーバーロードし複素数加算を実行- 和を含む新しい
TestClassインスタンスを返却 - 複素数を表示する
print()を実装 main()で2インスタンス作成、加算、結果出力
まとめ
- 演算子オーバーロードで、スコープ内で演算子に複数の意味を持たせられる
- ユーザー定義型にカスタム動作を提供
- ほとんどのC++演算子をオーバーロード可能だが、一部は不可
- 少なくとも1つのオペランドはユーザー定義型でなければならない
- 既存の演算子のみオーバーロード可能
C言語
- C++配列を関数に渡す完全ガイド:1次元・多次元配列の実例付き
- C++演算子を徹底解説:種類、例、サンプルプログラム付き
- C++ do-while文:構文、実践例、ネストしたループ
- C++ポインタをマスター:概念、例、実践的応用
- C++ char型をマスター:宣言、ASCII、変換テクニック
- C++構造体を実例で徹底解説
- C++のstd::listをマスターする:構文、関数、実践例
- C++関数を実例で徹底解説:基本から応用まで
- Python演算子オーバーロード完全ガイド:__add__、__lt__など特殊メソッドでOOP設計を強化
- Pythonラムダ関数をマスターする:実例とベストプラクティス
- Python round()関数を実例で徹底解説