演算子オーバーロード入門
CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 40/104。
演算子のオーバーロードを使用すると、+、-、== などの演算子がカスタムクラスで使用されたときにどのように動作するかを定義できます。a.add(b) のようなメソッドを呼び出す代わりに、より直感的な a + b と記述できます。
C++において、演算子は本質的に特別な名前を持つ関数です。演算子をオーバーロードするには、operatorキーワードの後に記号を続けて関数を定義します:
class Vector2D {
double x, y;
public:
Vector2D(double x, double y) : x(x), y(y) {}
// + 演算子をオーバーロードします
Vector2D operator+(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}
};これで、2つのベクトルを自然に足し合わせることができます。
Vector2D v1(1.0, 2.0);
Vector2D v2(3.0, 4.0);
Vector2D v3 = v1 + v2; // v1.operator+(v2) を呼び出しますすべての演算子がオーバーロードできるわけではありません。スコープ解決演算子 ::、メンバーアクセス .、三項演算子 ?:、および sizeof はオーバーロードできません。さらに、新しい演算子を作成したり、演算子の優先順位を変更したりすることはできません。* は常に + よりも前に評価されます。
演算子は、(上記のように)メンバ関数として実装することも、非メンバ関数として実装することもできます。今後のレッスンでは、それぞれの方法をいつ使用すべきか、また特定のカテゴリの演算子をオーバーロードする方法について学びます。
チャレンジ
簡単2D座標を表し、+ 演算子を使用して2つの点を加算できる Point クラスを作成しましょう。これは演算子オーバーロードへの第一歩です。カスタムクラスを使い慣れた演算子で動作させることができます。
コードを整理するために、2つのファイルを作成します:
Point.h: x座標とy座標(ともにint)を保持するPointクラスを定義します。クラスには以下を含める必要があります:- x座標とy座標のためのプライベートメンバ
- xとyの値を受け取るコンストラクタ
- ゲッター
getX()およびgetY()(ともに const) - 2つの点を加算し、合算された座標を持つ新しい
Pointを返す、オーバーロードされた+演算子
+演算子は、別のPointを const 参照で受け取り、新しいPointを返すメンバ関数として実装する必要があります。どちらのオペランドも変更しないため、constとしてマークしてください。main.cpp: 入力から4つの整数(別々の行にある x1, y1, x2, y2)を読み取り、2つの点を表します。2つのPointオブジェクトを作成し、+演算子を使用してそれらを加算し、結果を表示します。出力形式:
Point 1: (<x1>, <y1>) Point 2: (<x2>, <y2>) Sum: (<sum_x>, <sum_y>)
ここでの重要な洞察は、p1 + p2 が実際には舞台裏で p1.operator+(p2) を呼び出しているということです。演算子をオーバーロードすることで、Point p3 = p1.add(p2); のような記述の代わりに、Point p3 = p1 + p2; のような直感的なコードを書くことができます。
入力文字列を std::stoi() を使用して整数に変換してください。ヘッダーファイルにはヘッダーガードを忘れないでください。
チートシート
演算子のオーバーロードを使用すると、+、-、==などの演算子がカスタムクラスでどのように動作するかを定義でき、a.add(b)の代わりにa + bのような直感的な構文を使用できるようになります。
演算子をオーバーロードするには、operatorキーワードの後に記号を続けて関数を定義します。
class Vector2D {
double x, y;
public:
Vector2D(double x, double y) : x(x), y(y) {}
// + 演算子をオーバーロードする
Vector2D operator+(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}
};使用例:
Vector2D v1(1.0, 2.0);
Vector2D v2(3.0, 4.0);
Vector2D v3 = v1 + v2; // v1.operator+(v2) を呼び出す一部の演算子はオーバーロードできません:::、.、?:、およびsizeof。新しい演算子を作成したり、演算子の優先順位を変更したりすることはできません。
演算子は、メンバ関数または非メンバ関数として実装できます。
自分で試してみよう
#include <iostream>
#include <string>
#include "Point.h"
using namespace std;
int main() {
// 入力を読み込む
string line1, line2, line3, line4;
getline(cin, line1);
getline(cin, line2);
getline(cin, line3);
getline(cin, line4);
int x1 = stoi(line1);
int y1 = stoi(line2);
int x2 = stoi(line3);
int y2 = stoi(line4);
// TODO: 入力値を使用して2つの Point オブジェクトを作成する
// TODO: + 演算子を使用して2つのポイントを加算する
// TODO: 要求された形式で結果を出力する:
// Point 1: (<x1>, <y1>)
// Point 2: (<x2>, <y2>)
// Sum: (<sum_x>, <sum_y>)
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
3コンストラクタとデストラクタ
デフォルトコンストラクタ引数付きコンストラクタコピーコンストラクタムーブコンストラクタコンストラクタ初期化リスト委譲コンストラクタデストラクタ詳解Rule of Three / Five / Zeroまとめ - Stringクラス6演算子オーバーロード
演算子オーバーロード入門算術演算子のオーバーロード比較演算子のオーバーロードストリーム演算子代入演算子のオーバーロード[] と () 演算子のオーバーロード型変換演算子まとめ:Matrix クラス