2024-07-16 C++プログラミング練習
今日は演算子のオーバーロードについて学びました。
演算子のオーバーロードとは、+や-などの四則演算であったり、インクリメント、デクリメントや条件式をユーザーが定義して使用するものです。
始めは何のためにあんねん、いつ使うねん。と思っていたんですが、GPTさんに例題を出してもらったベクトルの問題で、演算子のオーバーロードに必要性を理解できました。
今回のGPTとのやり取りは以下のリンクにあります。
プロンプト
私はC++を勉強しています。
以下の条件を満たす実用的なプログラミングをつくる問題を作成してください。
サンプルプログラムも提示してください。
【必須要素】
・演算子のオーバーロード
【難易度】
エンジニア2年目
【コーディング量】
300行以上
【問題文中に以下の言葉は絶対に含んではいけません】
本、学生、学校、図書館、管理システム
問題
問題: 3Dベクトル計算クラスの作成
3Dベクトルの計算を行うためのクラスを作成してください。このクラスは、以下の要件を満たす必要があります。
要件
クラス名: Vector3D
メンバー変数:
double x:X軸の成分
double y:Y軸の成分
double z:Z軸の成分
コンストラクタ:
引数なしのコンストラクタ(初期値としてすべての成分を0にする)
3つの引数を取るコンストラクタ(指定された値で初期化する)
演算子のオーバーロード:
+ 演算子:2つのベクトルの和を計算する
- 演算子:2つのベクトルの差を計算する
* 演算子:ベクトルとスカラーの積を計算する(ベクトル * スカラー、スカラー * ベクトルの両方)
== 演算子:2つのベクトルが等しいかどうかを比較する
!= 演算子:2つのベクトルが等しくないかどうかを比較する
<< 演算子:ベクトルの内容を出力する
メンバー関数:
double magnitude() const: ベクトルの大きさを計算する
Vector3D normalize() const: 正規化されたベクトルを返す
double dot(const Vector3D& other) const: 内積を計算する
Vector3D cross(const Vector3D& other) const: 外積を計算する
作成したプログラム
#include <iostream>
#include <cmath>
class Vector3D {
private:
double x, y, z;
public:
// 引数なしのコンストラクタ
Vector3D() : x(0), y(0), z(0) {}
// 3つの引数を取るコンストラクタ
Vector3D(double x, double y, double z) : x(x), y(y), z(z) {}
// 演算子のオーバーロード
Vector3D operator+(const Vector3D& other) const {
return Vector3D(x + other.x, y + other.y, z + other.z);
}
Vector3D operator-(const Vector3D& other) const {
return Vector3D(x - other.x, y - other.y, z - other.z);
}
Vector3D operator*(double scalar) const {
return Vector3D(x * scalar, y * scalar, z * scalar);
}
friend Vector3D operator*(double scalar, const Vector3D& vec) {
return Vector3D(vec.x * scalar, vec.y * scalar, vec.z * scalar);
}
bool operator==(const Vector3D& other) const {
return x == other.x && y == other.y && z == other.z;
}
bool operator!=(const Vector3D& other) const {
return !(*this == other);
}
friend std::ostream& operator<<(std::ostream& os, const Vector3D& vec) {
os << "Vector3D(" << vec.x << ", " << vec.y << ", " << vec.z << ")";
return os;
}
// メンバー関数
double magnitude() const {
return std::sqrt(x * x + y * y + z * z);
}
Vector3D normalize() const {
double mag = magnitude();
return Vector3D(x / mag, y / mag, z / mag);
}
double dot(const Vector3D& other) const {
return x * other.x + y * other.y + z * other.z;
}
Vector3D cross(const Vector3D& other) const {
return Vector3D(
y * other.z - z * other.y,
z * other.x - x * other.z,
x * other.y - y * other.x
);
}
};
// サンプルプログラム
int main() {
Vector3D v1(1.0, 2.0, 3.0);
Vector3D v2(4.0, 5.0, 6.0);
Vector3D sum = v1 + v2;
Vector3D diff = v1 - v2;
Vector3D scalar_mult = v1 * 2.0;
Vector3D scalar_mult2 = 2.0 * v1;
double dot_product = v1.dot(v2);
Vector3D cross_product = v1.cross(v2);
std::cout << "v1: " << v1 << std::endl;
std::cout << "v2: " << v2 << std::endl;
std::cout << "Sum: " << sum << std::endl;
std::cout << "Difference: " << diff << std::endl;
std::cout << "Scalar Multiplication: " << scalar_mult << std::endl;
std::cout << "Scalar Multiplication (reverse): " << scalar_mult2 << std::endl;
std::cout << "Dot Product: " << dot_product << std::endl;
std::cout << "Cross Product: " << cross_product << std::endl;
return 0;
}
出力結果
このようにして、ベクトルの内積や外積を定義して、使用することができました。使い方もかなり単純で、今までメンバ関数の定義していた方法とほぼ同じです。関数名のところを「operator○○」とします。○○の部分は+や-など演算子の名前を入れます。
次回はスマートポインタを学びたいと思います。
今日もありがとうございました。