Version 16.21
演算子のオーバーロードの実例
「さて、今回は演算子のオーバーロードのまとめとして、演算子の
オーバーロードの実例を紹介します」
『実例?』
「そう、フル活用した例。今回は、以下のプログラムの〈int *pi〉の代わ
りになるクラスを作成します」
// Main.cpp
#include <Windows.h>
#include <stdio.h>
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
int iArray[5];
// forで全部セットします。
for
( int *pi = iArray
; pi != ( iArray + 5 )
; ++pi
)
{
*pi = 100;
}
// 配列の方を出力します。
char pch[256];
sprintf
( pch
, "%d, %d, %d, %d, %d\n"
, iArray[0]
, iArray[1]
, iArray[2]
, iArray[3]
, iArray[4]
);
OutputDebugString( pch );
// 100, 100, 100, 100, 100
return 0;
}
「このプログラムでは、ポインタをひとつずつ進めて、すべての要素に 100
をセットします」
『む、この for の使い方、見たことないかも』
for
( int *pi = iArray
; pi != ( iArray + 5 )
; ++pi
)
{
*pi = 100;
}
『えっと、まず int 型のポインタを作って、そこに iArray だから、配列
のアドレスを入れてるんだよね』
「そう、だからアドレス的には pi と iArray は同じになります」
『次に、……えっと、分解して、まず iArray + 5 は……』
「 Version 4.10 ( No.060 ) で説明したけど、 ++ 演算子をポインタに
使うと、その型のサイズ分増えるから」
『図にすると……』
iArray、pi iArray + 5
↓ ↓
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
← → ← → ← → ← → ← →
iArray[0] iArray[1] iArray[2] iArray[3] iArray[4]
『だよね、で、 iArray + 5 は……あれ、外にはみ出ちゃうね』
「そう、つまり iArray + 5 は〈配列のひとつ外側のアドレス〉ということ
になります」
『んーと、それと pi が違う間、 for でループする、ってことね。じゃあ
最後の ++pi は、これも4バイトずつ増えるから……』
iArray + 5
iArray、pi *pi(1) *pi(2) *pi(3) *pi(4) *pi(5)
↓ ↓ ↓ ↓ ↓ ↓
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
← → ← → ← → ← → ← →
iArray[0] iArray[1] iArray[2] iArray[3] iArray[4]
『そか、 ++ で増やしていくのって、結局 iArray の要素の先頭アドレスに
なるんだ!』
「そういうこと。その状態で *pi ってすれば」
『その要素の変数になる、ってことなんだね』
「で、最後に」
『ちょうど配列の一つ外のアドレスになるから、 iArray + 5 と一致する、
それまでループするってことね』
「そういうこと。配列の操作の方法には、こういう方法もあるから。実際に
使うことはなくても、プログラムの例では多いから憶えておいて」
『はーい』
「で、この pi の型を、クラスにしよう、というのが今回の話」
『……そんなことできるの?』
「もちろん。まず Version 16.01 ( No.328 ) の例を参考に、以下の
ソースファイルとヘッダーファイルを作成してください」
・ソースファイル
IntPointer.cpp
・ヘッダーファイル
IntPointer.h
『ってことはクラス名は CIntPointer ?』
「そう、このクラスは以下の演算子をオーバーロードして int 型ポインタ
と同じ機能を持つクラスにします」
・CIntPointerクラス
++ 演算子
!= 演算子
* 演算子
『お! これ全部作ったらさっきのが全部できるんだ!』
「それでは実際のプログラムを見てみましょう。まずヘッダーファイルか
ら」
// IntPointer.h
class CIntPointer
{
// int 型ポインタ。
int *m_pi;
public:
// コンストラクタ。
CIntPointer( int *p_pi );
// ++演算子。
int * operator ++();
// !=演算子。
BOOL operator !=( int *p_pi );
// *演算子。
int &operator *();
};
『 int のポインタと、コンストラクタ、3つの演算子のオーバーロード、だ
ね』
「ソースファイルは以下のようになります」
// IntPointer.cpp
#include <windows.h>
#include "IntPointer.h"
// コンストラクタ。
CIntPointer::CIntPointer( int *p_pi )
: m_pi( p_pi )
{
}
// ++演算子。
int * CIntPointer::operator ++()
{
return ++m_pi;
}
// !=演算子。
BOOL CIntPointer::operator !=( int *p_pi )
{
if( p_pi == m_pi )
{
return FALSE;
}
return TRUE;
}
// *演算子。
int &CIntPointer::operator *()
{
return *m_pi;
}
『お、意外とシンプル』
「というわけで、細かい説明と使用例は次回に続く!」
『ええ〜?』
/*
Preview Next Story!
*/
『意外とシンプルだからさくっと終わりそうだけど』
「そう思えるって事は、それだけ勉強してるってこと」
『んーっていうより慣れ始めてる?』
「それも勉強のうちだから」
『ホントに?』
「というわけで次回」
< Version 16.22 演算子のオーバーロードの実例、の続き >
『につづく!』
「英語耳みたいにプログラム目というか」
『何そのサイボーグみたいなの』