- 追加された行はこの色です。
- 削除された行はこの色です。
第10回は
演算子のオーバーロードについてです。
なんと、演算子も関数だった!?
(な、なんだってー)
基本的にはクラス内の演算子をオーバーロードします
2項演算子のオーバーロードは次のようになります
演算結果 operator 演算子(演算子の右辺)
書き方が難しいですが・・・
ちなみに左辺はクラス内部の変数となります
つまり
A + B
とやったとき
Aの+演算子関数が呼ばれます
#vote((^ω^)わかったお[0],普通[0],。(`ω´#)。わかりにくぃぜぇえええええ[0])
ためしに自作Int型を作って
演算子をオーバーロードして
計算してみましょう
#include <iostream>
using namespace std;
class Int{
public:
int data;
Int(){}
// コンストラクタ
Int(int Data):data(Data){}
~Int(){}
// 代入演算子のオーバーロード
Int& operator=(const Int& Obj){
cout << "call equal operator" << endl;
// this->はクラス内変数にアクセスするキーワード
this->data = Obj.data;
return *this;
}
// 加算演算子のオーバーロード
Int operator+(const Int& Obj){
cout << "call add operator" << endl;
// this->はクラス内変数にアクセスするキーワード
return Int(this->data + Obj.data);
}
};
int main(){
Int a(5),b(10);
Int c;
c = a + b;
cout << "c = " << c.data << endl;
return 0;
}
あまり恩恵を感じられないと思うので
より実践的な例を挙げときます
2次元ベクトルクラスの一部です
演算子のオーバーロードを使用することで
x,y2つのパラメータを同時に計算することができます
#include <iostream>
using namespace std;
class Vector2
{
private:
float x,y;
public:
// コンストラクタ
Vector2():x(0),y(0)
{}
// コンストラクタ
Vector2(float X,float Y):x(X),y(Y)
{}
// デストラクタ
~Vector2()
{}
// 代入演算子のオーバーロード
Vector2& operator =(const Vector2& obj){
// this->はクラス内変数にアクセスするキーワード
// クラス内のx,yに値代入
this->x = obj.x;
this->y = obj.y;
return *this;
}
// 加算代入演算子のオーバーロード
Vector2& operator +=(const Vector2& obj){
// this->はクラス内変数にアクセスするキーワード
// クラス内のx,yに値代入
this->x += obj.x;
this->y += obj.y;
return *this;
}
// 加算代入演算子のオーバーロード
Vector2 operator +(const Vector2& obj){
Vector2 vec;
// this->はクラス内変数にアクセスするキーワード
// クラス内のx,yに値代入
vec.x = this->x + obj.x;
vec.y = this->y + obj.y;
return vec;
}
// 配列のオーバーロード
float operator [](unsigned int i){
// このベクトルの先頭アドレス
float *p = &x;
return p[i];
}
// 単行演算子のオーバーロード
Vector2& operator++(){
this->x++;
this->y++;
return *this;
}
// 値をみる
void Show(){
cout << "x = " << x << endl;
cout << "y = " << y << endl;
}
};
int main(){
Vector2 vec1;
Vector2 vec2(1.0f,2.0f);
Vector2 vec3;
cout << "vec1" << endl;
vec1.Show();
cout << "vec2" << endl;
vec2.Show();
cout << "-----------------" <<endl;
vec1 = vec2;
cout << "vec1" << endl;
vec1.Show();
++vec1;
cout << "vec1" << endl;
vec1.Show();
vec1 += vec2;
cout << "vec1" << endl;
vec1.Show();
vec3= vec1 + vec2;
cout << "vec3" << endl;
vec3.Show();
cout << "vec3" << endl;
cout << "x = " << vec3[0] << endl;
cout << "y = " << vec3[1] << endl;
return 0;
}
ほかにも-演算子やら*演算子やらオーバーロードしないと
実用的ではありませんがそれは各自実装してください。
new、delete演算子などもオーバーロードすることができます
#include <new> // new オーバーロード用
#include <iostream>
using namespace std;
// new演算子のオーバーロード
// size 作成するオブジェクトのサイズ
void* operator new(size_t size) {
printf("This is operator new! size = %d\n", size);
return malloc(size);
}
// new[]演算子のオーバーロード
void* operator new[](size_t iSize) {
printf("This is oparator new[] size = %d\n", iSize);
return malloc(iSize);
}
// delete 演算子のオーバーロード
void operator delete(void* pv) {
printf("This is operator delete!\n");
free(pv);
}
// delete []演算子のオーバーロード
void operator delete[](void* pv) {
printf("This is operator delete[]!\n");
free(pv);
}
class Vector2
{
private:
float x,y;
public:
// コンストラクタ
Vector2()
{
cout << "create" << endl;
}
// デストラクタ
~Vector2()
{
cout << "destroy" << endl;
}
};
int main(){
// new deleteのオーバーロードはコンパイラによって動作違うみたいなので
// 使うときは慎重に、極力使わないように!
// operator new
Vector2* newdel = new Vector2;
// operator delete
delete newdel;
// operator new[]
Vector2* newdelarray = new Vector2[2];
// operator delete[]
delete[] newdelarray;
return 0;
}
new、delete演算子はアロケータ(メモリ割り当て、管理をするクラス)を
作成するときに必要ですが、それ以外では使わないので
極力使わないほうが無難でしょう
ただし、オーバーロードできるものであるという認識は重要です
演算子のオーバーロードは
使い方を間違えると非常にわかりにくくなるので
ベクトルクラスなどの計算以外での使用は極力避けたいものです
ただし、うまく使えば非常に強力なものなので
覚えておいて損はないはずです
ネタとしてはほかにも推論エンジンなどの
面白い使い方などができるような気がします
#vote((^ω^)わかったお[1],普通[0],。(`ω´#)。わかりにくぃぜぇえええええ[0])