クラスの応用_演算子のオーバーロード
int型の計算で、
int a; a = 1 + 2;
と「+」をつかって2つの整数を足すことができる。
作成したクラスでもint型のように2つのオペランドについて
演算できるようにしたい。
例えば社員数と資本金をメンバに持つ会社クラスを使って、
二つの会社(オブジェクト)を作ったとします。
この会社を合併して新しい会社を設立したい!!
【プログラムのイメージ】
Corp mac(100,2000); Corp win(50,1000); Corp tama = mac + win; tama.disp();
【実行結果のイメージ】
$ testOperator.cpp 社員数 150人、資本金 3000万円です。 $
※このプログラムはフィクションです。実在の人物や団体とは関係ありません。
こんな感じでしょうか。
こんな関数があったらどうにかなりそう。
これをこうやって・・・
// Corp tama = mac + win;
Corp tama = mac.sum(win);
こうして・・・
Corp sum(Corp c){
Corp obj;
obj.members = 呼び元のmacオブジェクト自身のmembers + winオブジェクト自身のmembers
obj.money = macオブジェクト自身のmoney + winオブジェクト自身のmoney
return obj;
}
さっきのところに戻ってみて確認
// Corp tama = mac + win;
Corp tama = mac.sum(win);
↑ ここにはCorp型のオブジェクトobjが返ってくるので、それをtamaにコピー
これでいけそうですね。
しかし、「+」を使いたいわけです。
でも「+」は整数どうしの計算にも使っているので、それを横取りするわけにもいかないし・・・。
そうです、オーバーロードします。
引数がCorpの時は自分が実装した本来の処理とは異なる処理を行うように。
長々と回りくどくなってきましたので、この辺にして実際の実装を見てみます。
【プログラム例】
#include <iostream> #include <string> using namespace std; class Corp { private: int members; int money; public: Corp(int mem = 0, int mon = 0) : // デフォルトコンストラクタにしておかないと・・・ members(mem), money(mon){} Corp operator+(Corp c){ Corp sum; // 関数内の処理に使う一時的なオブジェクトsumに引数が必要になってしまう。 sum.members = members + c.members; sum.money = money + c.money; return sum; } void disp(){ cout << "社員数 " << members << "人、資本金" << money << "万円です。" << endl; } }; int main(){ Corp mac(100,2000); Corp win(50,1000); cout << "起業しました。\n" << endl; cout << "mac株式会社は・・・" << endl; mac.disp(); cout << "win株式会社は・・・" << endl; win.disp(); Corp tama = mac + win; cout << "合併しました。\n" << endl; cout << "合併後のtama株式会社は・・・" << endl; tama.disp(); return 0; }
【実行結果】
起業しました。 mac株式会社は・・・ 社員数 100人、資本金2000万円です。 win株式会社は・・・ 社員数 50人、資本金1000万円です。 合併しました。 合併後のtama株式会社は・・・ 社員数 150人、資本金3000万円です。
これを見てみると分かりますが、
A = B + C;
に使われる「+」のような演算子をオーバーロードする際はちょっと普通の関数とは異なります。
「operator+」という関数名で定義してやればいいわけですね。
「operator+」という関数を引数や戻り値を意識して自分で実装する、使う時は普通の関数とはちょっと違う、それだけで、後はそこまで難しいことではない(はず)です。
自分で「-」演算子を作ってみると面白いかもしれない。
例えば、
「リストラ社員数30人、損失額700万円のCorpクラスのfukeikiオブジェクトを作り、自分で実装した「-」オブジェクトを使って引き算してみる」とか・・・。
左辺が自分のクラスじゃない場合
はい、次に疑問になるのは、左辺がCorpクラスでない場合です。
特に、Corpでない場合、Corpクラスのメンバ関数にはできません。
でもCorpクラスのprivateな変数にアクセスしたい。
例えば、「好景気が来たので社員数も資本金も100ずつ増えました」というときに、
tama = 100 + tama;
このように使いたいわけです。
そんな時はフレンド関数を作成します。
要は、Corpクラスにfriend指定して「operator+」関数の宣言だけしておき、
あとは、Corpクラスではないので、Corpクラスの外に定義します。
【イメージ】
class Corp{ public: friend Corp operator+(int plus, Corp c); // 宣言 }; Corp operator+(int plus, Corp c){ // 定義 Corp p; p.members = c.members + plus; p.money = c.money + plus; return p; }
ここで一つ、重要なのは「左辺の値を第一引数で受け取る」ということ。
これを踏まえて・・・
【プログラム例】
#include <iostream> #include <string> using namespace std; class Corp { private: int members; int money; public: Corp(int mem = 0, int mon = 0) : members(mem), money(mon){} friend Corp operator+(int plus, Corp c); void disp(){ cout << "社員数 " << members << "人、資本金" << money << "万円です。" << endl; } }; Corp operator+(int plus, Corp c){ Corp p; p.members = c.members + plus; p.money = c.money + plus; return p; } int main(){ Corp mac(100,2000); cout << "起業しました。\n" << endl; cout << "mac株式会社は・・・" << endl; mac.disp(); mac = 100 + mac; cout << "好景気になって、社員数も資本金も100増えました!!\n" << endl; cout << "現在のmac株式会社は・・・" << endl; mac.disp(); return 0; }
【実行結果】
起業しました。 mac株式会社は・・・ 社員数 100人、資本金2000万円です。 好景気になって、社員数も資本金も100増えました!! 現在のmac株式会社は・・・ 社員数 200人、資本金2100万円です。
今回のように左辺と右辺で2つのオペランドを持つ場合(2項演算子)とは違って、
一つしかオペランドを持たないことがある(単項演算子)。
これについての説明は割愛する。
※なお、問題集には取り込んでいる。(クラスの応用1 - Awesome Hacks!)
以上。