【C++】オペレーターでの演算子のオーバーロード

## Unity機能を作ろう!
**用途 : クラスのオブジェクトを組み込み型のように扱う**

基本形 : `型　operator 演算子(引数) { 処理文 }`

### Vector2
```C++:Vector2.h
#pragma once

class Vector2
{
public:
#pragma region 特殊(定数)ベクトルの宣言
	static const Vector2 zero;
	static const Vector2 one;
	static const Vector2 up;
	static const Vector2 down;
	static const Vector2 left;
	static const Vector2 right;
#pragma endregion

#pragma region XY
	// 共用体
	union
	{
		// 無名構造体(アノニマス構造体)でラップする
		struct
		{
			float x, y;
		};
		float value[2];
	};
#pragma endregion

#pragma region コンストラクタとデストラクタ
	Vector2() = default;
	Vector2(const Vector2&) = default;	// コピーコンストラクタ
	//Vector2(const Vector2&&);			// ムーブコンストラクタ
	Vector2(float x, float y);
	Vector2(float v[2]);
	virtual ~Vector2() = default;
#pragma endregion

#pragma region 演算子のオーバーロード(演算子の追加)
	// 四則演算(2項演算子)
	Vector2 operator + (const Vector2& v) const;
	Vector2 operator - (const Vector2& v) const;
	Vector2 operator * (const float& v) const;
	Vector2 operator / (const float& v) const;

	// 代入演算(2項演算子)
	const Vector2& operator= (const Vector2& v);
	const Vector2& operator+=(const Vector2& v);
	const Vector2& operator-=(const Vector2& v);
	const Vector2& operator*=(const float& v);
	const Vector2& operator/=(const float& v);

	// 単項演算子 -
	const Vector2& operator- ();

	// 比較演算子
	bool operator==(const Vector2& v)const;
	bool operator!=(const Vector2& v)const;
#pragma endregion

#pragma region Unity関数(代入なし, 内部使用).
	float Magnitude()const;
	float SqrMagnitude()const;
	Vector2 Normalize()const;
#pragma endregion

#pragma region Unity関数(代入あり, 外部使用)
	static float Magnitude(const Vector2& v);
	static float SqrMagnitude(const Vector2& v);
	static Vector2 Normalize(const Vector2& v);
	static float Distance(const Vector2& v1, const Vector2& v2);
	static float Dot(const Vector2& v1, const Vector2& v2);
	static float Angle(const Vector2& v1, const Vector2& v2);
#pragma endregion
};
```

```C++:Vector2.cpp
#include "Vector2.h"

// 特殊(定数)ベクトルの定義
const Vector2 Vector2::zero = { 0,0 };
const Vector2 Vector2::one = { 1,1 };
const Vector2 Vector2::up = { 0,1 };
const Vector2 Vector2::down = { 0,-1 };
const Vector2 Vector2::left = { -1,0 };
const Vector2 Vector2::right = { 1,0 };

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="x">x座標の初期化値</param>
/// <param name="y">y座標の初期化値</param>
Vector2::Vector2(float x, float y)
	:x(x)
	, y(y)
{}

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="x">x座標の初期化値</param>
/// <param name="y">y座標の初期化値</param>
Vector2::Vector2(float v[2])
	:x(v[0])
	, y(v[1])
{}

/// <returns>Vector2同士の足し算の結果</returns>
Vector2 Vector2::operator+(const Vector2& v)const
{
	return Vector2(this->x + v.x, this->y + v.y);
}

/// <returns>Vector2同士の引き算の結果</returns>
Vector2 Vector2::operator-(const Vector2& v) const
{
	return Vector2(this->x - v.x, this->y - v.y);
}

/// <returns>float値をVector2の要素にそれぞれを掛けた結果</returns>
Vector2 Vector2::operator*(const float& v) const
{
	return Vector2(this->x * v, this->y * v);
}

/// <returns>float値をVector2の要素にそれぞれを割った結果</returns>
Vector2 Vector2::operator/(const float& v) const
{
	if (v == 0)return 0;
	return Vector2(this->x / v, this->y / v);
}

/// <summary>
/// Vector2からVector2へ代入する
/// </summary>
const Vector2& Vector2::operator=(const Vector2& v)
{
	this->x = v.x;
	this->y = v.y;
	return *this;
}

/// <summary>
/// Vector2にVector2を足す
/// </summary>
const Vector2& Vector2::operator+=(const Vector2& v)
{
	this->x += v.x;
	this->y += v.y;
	return *this;
}

/// <summary>
/// Vector2からVector2を引く
/// </summary>
const Vector2& Vector2::operator-=(const Vector2& v)
{
	this->x -= v.x;
	this->y -= v.y;
	return *this;
}

/// <summary>
/// Vector2のそれぞれの要素にfloat値を掛ける
/// </summary>
const Vector2& Vector2::operator*=(const float& v)
{
	this->x *= v;
	this->y *= v;
	return *this;
}

/// <summary>
/// Vector2のそれぞれの要素からfloat値を割る
/// </summary>
const Vector2& Vector2::operator/=(const float& v)
{
	if (v == 0)return 0;
	this->x /= v;
	this->y /= v;
	return *this;
}

/// <summary>
/// Vector2の符号を反転させる
/// </summary>
const Vector2& Vector2::operator-()
{
	return (*this * (-1));
}

/// <returns>true = 引数のVector2と全く同じ, false = 引数のVector2と異なる</returns>
bool Vector2::operator==(const Vector2& v) const
{
	return this->x == v.x && this->y == v.y;
}

/// <returns>true = 引数のVector2と異なる部分がある, false = 引数のVector2と全く同じ</returns>
bool Vector2::operator!=(const Vector2& v) const
{
	return this->x != v.x || this->y != v.y;
}

//#include<math.h>	// C言語の数学ヘッダー
#include<cmath>		// C++の数学ヘッダー

/// <returns>ベクトルの大きさ</returns>
float Vector2::Magnitude()const
{
	// sqrtは平方根の計算
	return 	std::sqrtf(this->x * this->x + this->y * this->y);
}

/// <returns>ベクトルの大きさ(平方根除外済み)</returns>
float Vector2::SqrMagnitude()const
{
	// 平方根を避ける
	return 	Magnitude() * Magnitude();
}

/// <summary>
/// 正規化
/// </summary>
Vector2 Vector2::Normalize()const
{
	return *this / this->Magnitude();
}

/// <returns>ベクトルの大きさ</returns>
float Vector2::Magnitude(const Vector2& v)
{
	// sqrtは平方根の計算
	return std::sqrtf(v.x * v.x + v.y * v.y);
}

/// <returns>ベクトルの大きさ(平方根除外済み)</returns>
float Vector2::SqrMagnitude(const Vector2& v)
{
	// 平方根を避ける
	return Magnitude(v) * Magnitude(v);
}

/// <summary>
/// 正規化
/// </summary>
Vector2 Vector2::Normalize(const Vector2& v)
{
	return v / v.Magnitude();
}

/// <summary>
/// Vector2からVector2の距離を測る
/// </summary>
float Vector2::Distance(const Vector2& v1, const Vector2& v2)
{
	//return std::sqrtf((v1.x-v2.x)*(v1.x-v2.x)+(v1.y-v2.y)*(v1.y-v2.y));
	return Magnitude(v1 - v2);
}

/// <returns>Vector2同士の掛け算の結果(内積)</returns>
float Vector2::Dot(const Vector2& v1, const Vector2& v2)
{
	return v1.x * v2.x + v1.y * v2.y;
}

/// <returns>ベクトルの間の角度(範囲 : 0 ~ 180度)</returns>
float Vector2::Angle(const Vector2& v1, const Vector2& v2)
{
	//　acosはアークコサインの計算
	return acos(Dot(v1.Normalize(), v2.Normalize())) * 180;
}
```
### Vector3
```C++:Vector3.h
#pragma once

class Vector3
{
public:
#pragma region 特殊(定数)ベクトルの宣言
	static const Vector3 zero;
	static const Vector3 one;
	static const Vector3 up;
	static const Vector3 down;
	static const Vector3 left;
	static const Vector3 right;
	static const Vector3 forward;
	static const Vector3 back;
#pragma endregion

#pragma region XYZ
	// 共用体
	union
	{
		// 無名構造体(アノニマス構造体)でラップする
		struct
		{
			float x, y, z;
		};
		float value[3];
	};
#pragma endregion

#pragma region コンストラクタとデストラクタ
	Vector3() = default;
	Vector3(const Vector3&) = default;	// コピーコンストラクタ
	//Vector3(const Vector3&&);			// ムーブコンストラクタ
	Vector3(float x, float y, float z = 0.0f);
	Vector3(float v[3]);
	virtual ~Vector3() = default;
#pragma endregion

#pragma region 演算子のオーバーロード(演算子の追加)
	// 四則演算(2項演算子)
	Vector3 operator + (const Vector3& v) const;
	Vector3 operator - (const Vector3& v) const;
	Vector3 operator * (const float& v) const;
	Vector3 operator / (const float& v) const;

	// 代入演算(2項演算子)
	const Vector3& operator= (const Vector3& v);
	const Vector3& operator+=(const Vector3& v);
	const Vector3& operator-=(const Vector3& v);
	const Vector3& operator*=(const float& v);
	const Vector3& operator/=(const float& v);

	// 単項演算子 -
	const Vector3& operator- ();

	// 比較演算子
	bool operator==(const Vector3& v)const;
	bool operator!=(const Vector3& v)const;
#pragma endregion

#pragma region Unity関数(代入なし, 内部使用).
	float Magnitude()const;
	float SqrMagnitude()const;
	Vector3 Normalize()const;
#pragma endregion

#pragma region Unity関数(代入あり, 外部使用)
	static float Magnitude(const Vector3& v);
	static float SqrMagnitude(const Vector3& v);
	static Vector3 Normalize(const Vector3& v);
	static float Distance(const Vector3& v1, const Vector3& v2);
	static float Dot(const Vector3& v1, const Vector3& v2);
	static float Cross(const Vector3& v1, const Vector3& v2);
	static float Angle(const Vector3& v1, const Vector3& v2);
#pragma endregion
};
```

```C++:Vector3.cpp
#include "Vector3.h"

// 特殊(定数)ベクトルの定義
const Vector3 Vector3::zero = { 0,0,0 };
const Vector3 Vector3::one = { 1,1,1 };
const Vector3 Vector3::up = { 0,1,0 };
const Vector3 Vector3::down = { 0,-1,0 };
const Vector3 Vector3::left = { -1,0,0 };
const Vector3 Vector3::right = { 1,0,0 };
const Vector3 Vector3::forward = { 0,0,1 };
const Vector3 Vector3::back = { 0,0,-1 };

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="x">x座標の初期化値</param>
/// <param name="y">y座標の初期化値</param>
/// <param name="z">z座標の初期化値</param>
Vector3::Vector3(float x, float y, float z)
	:x(x)
	, y(y)
	, z(z)
{}

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="x">x座標の初期化値</param>
/// <param name="y">y座標の初期化値</param>
/// <param name="z">z座標の初期化値</param>
Vector3::Vector3(float v[3])
	:x(v[0])
	, y(v[1])
	, z(v[2])
{}

/// <returns>Vector3同士の足し算の結果</returns>
Vector3 Vector3::operator+(const Vector3& v)const
{
	return Vector3(this->x + v.x, this->y + v.y, this->z + v.z);
}

/// <returns>Vector3同士の引き算の結果</returns>
Vector3 Vector3::operator-(const Vector3& v) const
{
	return Vector3(this->x - v.x, this->y - v.y, this->z - v.z);
}

/// <returns>float値をVector3の要素にそれぞれを掛けた結果</returns>
Vector3 Vector3::operator*(const float& v) const
{
	return Vector3(this->x * v, this->y * v, this->z * v);
}

/// <returns>float値をVector3の要素にそれぞれを割った結果</returns>
Vector3 Vector3::operator/(const float& v) const
{
	if (v == 0)return 0;
	return Vector3(this->x / v, this->y / v, this->z / v);
}

/// <summary>
/// Vector3からVector3へ代入する
/// </summary>
const Vector3& Vector3::operator=(const Vector3& v)
{
	this->x = v.x;
	this->y = v.y;
	this->z = v.z;
	return *this;
}

/// <summary>
/// Vector3にVector3を足す
/// </summary>
const Vector3& Vector3::operator+=(const Vector3& v)
{
	this->x += v.x;
	this->y += v.y;
	this->z += v.z;
	return *this;
}

/// <summary>
/// Vector3からVector3を引く
/// </summary>
const Vector3& Vector3::operator-=(const Vector3& v)
{
	this->x -= v.x;
	this->y -= v.y;
	this->z -= v.z;
	return *this;
}

/// <summary>
/// Vector3のそれぞれの要素にfloat値を掛ける
/// </summary>
const Vector3& Vector3::operator*=(const float& v)
{
	this->x *= v;
	this->y *= v;
	this->z *= v;
	return *this;
}

/// <summary>
/// Vector3のそれぞれの要素からfloat値を割る
/// </summary>
const Vector3& Vector3::operator/=(const float& v)
{
	if (v == 0)return 0;
	this->x /= v;
	this->y /= v;
	this->z /= v;
	return *this;
}

/// <summary>
/// Vector3の符号を反転させる
/// </summary>
const Vector3& Vector3::operator-()
{
	return (*this * (-1));
}

/// <returns>true = 引数のVector3と全く同じ, false = 引数のVector3と異なる</returns>
bool Vector3::operator==(const Vector3& v) const
{
	return this->x == v.x && this->y == v.y && this->z == v.z;
}

/// <returns>true = 引数のVector3と異なる部分がある, false = 引数のVector3と全く同じ</returns>
bool Vector3::operator!=(const Vector3& v) const
{
	return this->x != v.x || this->y != v.y || this->z != v.z;
}

//#include<math.h>	// C言語の数学ヘッダー
#include<cmath>		// C++の数学ヘッダー

/// <returns>ベクトルの大きさ</returns>
float Vector3::Magnitude()const
{
	// sqrtは平方根の計算
	return 	std::sqrtf(this->x * this->x + this->y * this->y + this->z * this->z);
}

/// <returns>ベクトルの大きさ(平方根除外済み)</returns>
float Vector3::SqrMagnitude()const
{
	// 平方根を避ける
	return 	Magnitude() * Magnitude();
}

/// <summary>
/// 正規化
/// </summary>
Vector3 Vector3::Normalize()const
{
	return *this / this->Magnitude();
}

/// <returns>ベクトルの大きさ</returns>
float Vector3::Magnitude(const Vector3& v)
{
	// sqrtは平方根の計算
	return std::sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
}

/// <returns>ベクトルの大きさ(平方根除外済み)</returns>
float Vector3::SqrMagnitude(const Vector3& v)
{
	// 平方根を避ける
	return Magnitude(v) * Magnitude(v);
}

/// <summary>
/// 正規化
/// </summary>
Vector3 Vector3::Normalize(const Vector3& v)
{
	return v / v.Magnitude();
}

/// <summary>
/// Vector3からVector3の距離を測る
/// </summary>
float Vector3::Distance(const Vector3& v1, const Vector3& v2)
{
	//return std::sqrtf((v1.x-v2.x)*(v1.x-v2.x)+(v1.y-v2.y)*(v1.y-v2.y)+(v1.z-v2.z)*(v1.z-v2.z));
	return Magnitude(v1 - v2);
}

/// <returns>Vector3同士の掛け算の結果(内積)</returns>
float Vector3::Dot(const Vector3& v1, const Vector3& v2)
{
	return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}

/// <returns>外積</returns>
float Vector3::Cross(const Vector3& v1, const Vector3& v2)
{
	return v1.x * v2.y - v1.x * v2.z,
		v1.y* v2.x - v1.y * v2.z,
		v1.z* v2.x - v1.z * v2.y;
}

/// <returns>ベクトルの間の角度(範囲 : 0 ~ 180度)</returns>
float Vector3::Angle(const Vector3& v1, const Vector3& v2)
{
	//　acosはアークコサインの計算
	return acos(Dot(v1.Normalize(), v2.Normalize())) * 180;
}
```

### Color
```C++:Color.h
#pragma once

class Color
{
public:
#pragma region 特殊(定数)ベクトルの宣言
	static const Color black;
	static const Color blue;
	static const Color clear;
	static const Color cyan;
	static const Color gray;
	static const Color green;
	static const Color grey;
	static const Color magenta;
	static const Color red;
	static const Color white;
	static const Color yellow;
#pragma endregion

#pragma region RGBA
	// 共用体
	union
	{
		// 無名構造体(アノニマス構造体)でラップする
		struct
		{
			float r, g, b, a;
		};
		float value[4];
	};
#pragma endregion

#pragma region コンストラクタとデストラクタ
	Color() = default;
	Color(const Color&) = default;	// コピーコンストラクタ
	//Vector3(const Vector3&&);			// ムーブコンストラクタ
	Color(float r, float g, float b, float a);
	Color(float v[4]);
	virtual ~Color() = default;
#pragma endregion

#pragma region 演算子のオーバーロード(演算子の追加)
	// 四則演算(2項演算子)
	Color operator + (const Color& v) const;
	Color operator - (const Color& v) const;
	Color operator * (const float& v) const;
	Color operator / (const float& v) const;

	// 代入演算(2項演算子)
	const Color& operator= (const Color& v);
	const Color& operator+=(const Color& v);
	const Color& operator-=(const Color& v);
	const Color& operator*=(const float& v);
	const Color& operator/=(const float& v);

	// 比較演算子
	bool operator==(const Color& v)const;
	bool operator!=(const Color& v)const;
#pragma endregion
};
```

```C++:Color.cpp
#include "Color.h"

// 特殊(定数)ベクトルの定義
const Color Color::black = { 0,0,0,1 };
const Color Color::blue = { 0,0,1,1 };
const Color Color::clear = { 0,0,0,0 };
const Color Color::cyan = { 0,1,1,1 };
const Color Color::gray = { 0.5f,0.5f,0.5f,1 };
const Color Color::green = { 0,1,0,0 };
const Color Color::grey = { 0.5f,0.5f,0.5f,1 };
const Color Color::magenta = { 1,0,1,1 };
const Color Color::red = { 1,0,0,1 };
const Color Color::white = { 1,1,1,1 };
const Color Color::yellow = { 1,0.92f,0.016f,1 };

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="r">赤色の初期化値</param>
/// <param name="g">緑色の初期化値</param>
/// <param name="b">青色の初期化値</param>
/// <param name="a">透明度の初期化値</param>
Color::Color(float r, float g, float b, float a)
	:r(r)
	, g(g)
	, b(b)
	, a(a)
{}

/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="r">赤色の初期化値</param>
/// <param name="g">緑色の初期化値</param>
/// <param name="b">青色の初期化値</param>
/// <param name="a">透明度の初期化値</param>
Color::Color(float v[4])
	:r(v[0])
	, g(v[1])
	, b(v[2])
	, a(v[3])
{}

/// <returns>Color同士の足し算の結果</returns>
Color Color::operator+(const Color& v)const
{
	return Color(this->r + v.r, this->g + v.g, this->b + v.b, this->a + v.a);
}

/// <returns>Color同士の引き算の結果</returns>
Color Color::operator-(const Color& v) const
{
	return Color(this->r - v.r, this->g - v.g, this->b - v.b, this->a - v.a);
}

/// <returns>float値をColorの要素にそれぞれを掛けた結果</returns>
Color Color::operator*(const float& v) const
{
	return Color(this->r * v, this->g * v, this->b * v, this->a * v);
}

/// <returns>float値をColorの要素にそれぞれを割った結果</returns>
Color Color::operator/(const float& v) const
{
	if (v == 0)return 0;
	return Color(this->r / v, this->g / v, this->b / v, this->a / v);
}

/// <summary>
/// ColorからColorへ代入する
/// </summary>
const Color& Color::operator=(const Color& v)
{
	this->r = v.r;
	this->g = v.g;
	this->b = v.b;
	this->a = v.a;
	return *this;
}

/// <summary>
/// ColorにColorを足す
/// </summary>
const Color& Color::operator+=(const Color& v)
{
	this->r += v.r;
	this->g += v.g;
	this->b += v.b;
	this->a += v.a;
	return *this;
}

/// <summary>
/// ColorからColorを引く
/// </summary>
const Color& Color::operator-=(const Color& v)
{
	this->r -= v.r;
	this->g -= v.g;
	this->b -= v.b;
	this->a -= v.a;
	return *this;
}

/// <summary>
/// Colorのそれぞれの要素にfloat値を掛ける
/// </summary>
const Color& Color::operator*=(const float& v)
{
	this->r *= v;
	this->g *= v;
	this->b *= v;
	this->a *= v;
	return *this;
}

/// <summary>
/// Colorのそれぞれの要素からfloat値を割る
/// </summary>
const Color& Color::operator/=(const float& v)
{
	if (v == 0)return 0;
	this->r /= v;
	this->g /= v;
	this->b /= v;
	this->a /= v;
	return *this;
}

/// <returns>true = 引数のColorと全く同じ, false = 引数のColorと異なる</returns>
bool Color::operator==(const Color& v) const
{
	return this->r == v.r && this->g == v.g && this->b == v.b && this->a == v.a;
}

/// <returns>true = 引数のColorと異なる部分がある, false = 引数のColorと全く同じ</returns>
bool Color::operator!=(const Color& v) const
{
	return this->r != v.r || this->g != v.g || this->b != v.b || this->a != v.a;
}
```