Version 16.17
演算子のオーバーロードの戻り値の型
「前回は、演算子のオーバーロードの、基本的なルールについて説明しまし
た」
『二項演算子に絞って考えると、結構分かりやすいかも』
「今回は、補足的な部分を説明していきます。まず、戻り値の型について」
『 , の時は CData クラスの参照だったね』
「まず、基本的に戻り値の型は決められていません。好きな戻り値にしても
いいし、 void でも構いません」
// , 演算子のオーバーロードメンバ関数。
void CData::operator , ( int p_i )
{
// 引数をメンバ変数にセットします。
m_iData = p_i;
}
「こんな感じに、戻り値を void にして、何も返さないのも問題ありませ
ん」
『でも、この前のだと、 *this 返してたよね』
// , 演算子のオーバーロードメンバ関数。
CData & CData::operator , ( int p_i )
{
// 引数をメンバ変数にセットします。
m_iData = p_i;
// 自分の参照を返します。
return *this;
}
『こうする理由があるんでしょ?』
「そう、自クラスの参照を戻り値の型にして、 *this で〈自分の参照〉を
返すと、こういうことができるようになるんです」
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
// CData クラスの変数を宣言します。
CData cData;
// ,演算子のオーバーロードメンバ関数を使用します。
cData , 100 , 100;
return 0;
}
『あ、【,】がひとつ増えてる!』
「これは、まず〈 cData , 100 〉が処理されて、その結果 cData の参照が
返されて、その参照を使って〈 参照 , 100 〉が処理されているんです」
『なるほど、戻り値に自クラスの参照使うと、それをさらに他の演算子に使
う事ができるんだ』
「これが重要なのは、 = 演算子のオーバーロード。たとえば、普通の int
型の場合でも、以下のようなことができます。
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
int i1;
int i2;
i1 = i2 = 100;
return 0;
}
『 i1 と i2 の両方に 100 を入れてるって事?』
「そういうこと。こういうことができるようにするために、自クラスの参照
を戻り値にするんです。たとえば = 演算子をオーバーロードする時には、
このようにします。
// Data.h
// CDataクラス。
class CData
{
public:
// private メンバ変数。
int m_iData;
public:
// = 演算子のオーバーロードメンバ関数。
CData & operator = ( int p_i );
};
// Data.cpp
#include <Windows.h>
#include <stdio.h>
#include "Data.h"
// = 演算子のオーバーロードメンバ関数。
CData & CData::operator = ( int p_i )
{
// 引数をメンバ変数にセットします。
m_iData = p_i;
// 自分の参照を返します。
return *this;
}
// Main.cpp
#include <Windows.h>
#include <stdio.h>
#include "Data.h"
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
// CData クラスの変数を宣言します。
CData cData1;
CData cData2;
// = 演算子のオーバーロードメンバ関数を使用します。
cData1 = cData2 = 100;
return 0;
}
『うわ、さっきの int の時と同じ事ができてる!』
「逆に言うと、戻り値の型を自クラスの参照にしないとこういうことができ
ないってことでもあるんです」
『……それを知っていないといけない?』
「そういうこと。こういうテクニックを知っていないと、演算子らしくなら
ない、ってことかな」
『演算子らしく……』
「これはメンバ関数版じゃない、普通の関数の時でもそう。たとえば、
+ 演算子のオーバーロード関数を作る場合」
// Data.h
// 略
// + 演算子のオーバーロード関数。
CData & operator + ( CData &p_rcData, int p_i );
// Data.cpp
// 略
// + 演算子のオーバーロード関数。
CData & operator + ( CData &p_rcData, int p_i )
{
p_rcData.m_iData = p_i;
return p_rcData;
}
『あ、引数を戻り値にしてる!』
「こうすると、以下のように + 演算子を使用することができます」
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
// CData クラスの変数を宣言します。
CData cData1;
CData cData2;
// = 演算子のオーバーロードメンバ関数を使用します。
cData1 = cData2 + 100 + 200;
return 0;
}
「〈 cData2 + 100 + 200 〉の所がそう」
『まず〈 cData2 + 100 〉やって、そうすると cData2 が参照で返されて、
さらに〈 cData2 + 200 〉が……ってこと?』
「そういうこと。こういうことができるように、引数を CData クラスの参照
にしているんです」
『あ、参照で返すために参照にしてるんだ!』
「これも、より自然に使えるようにするためのテクニック」
『テクニック……』
「言い換えると、必須じゃないんです。演算子のオーバーロードは、確かに
ある程度のルールはあるけど、それさえクリアできればコンパイルは通るし
使うこともできます。でも、それをより使いやすくするためには」
『こういうテクニックを知っていて、プログラムしなきゃいけない』
「そうしないと、演算子として自然にはならない、ってことなんです」
『作る側の責任って感じねー』
「自分で使う分には作り込まなくてもいいんだけど、誰かが使う場合にはか
なりこだわって作らないと難しいかもね」
『いや、自分のためになんか使わないしこれ……』
/*
Preview Next Story!
*/
『演算子のオーバーロードもそろそろ終わり?』
「いや、あと2回は続くけど」
『げ!』
「げってなにげって」
『だって自分じゃ使わないし!』
「というわけで次回」
< Version 16.18 単項演算子のオーバーロード >
『につづく!』
「 STL 教えたら使いたくなるかな……」
『う、なんだかワルダクミの声が聞こえる……』