Version 17.19
インターフェイスの使い方
「前回は」
『よく分からなかった!』
「というわけでちゃんとまとめてみます。まず、ポリモーフィズムの一番良
く使われる場面は?」
『関数ポインタの代わり!』
「そう、自分で作った関数を呼び出してもらうためにアドレスを渡すのが
関数ポインタ、それをもう少し分かりやすくしたのが」
『ポリモーフィズムの機能ってわけね』
「この部分だけを抜き出してみようか。まずは関数ポインタの場合」
■関数ポインタの場合
◇準備
(関数Aのアドレスを渡す)
┌──使われる側────┐ ┌────使う側───┐
│ ・関数Aを呼び出す関数 ←←←←←←・関数A │
└───────────┘ └──────────┘
◇使う時
(関数Aを呼び出す)
┌──使われる側────┐ ┌────使う側───┐
│ ・関数Aを呼び出す関数 →→→→→→・関数A │
└───────────┘ └──────────┘
『つまり、使う側で関数を用意してアドレスを渡しておくと、それを呼び出
してくれるわけね』
「そういうこと。これをポリモーフィズムで実現すると、こうなります」
■ポリモーフィズムの場合
◇準備
(派生クラスの変数のアドレスを渡す)
┌──使われる側────┐ ┌────使う側──────┐
│ ・クラスAの仮想関数を ←←←←←←・クラスAの派生クラス。 │
│ を呼び出す関数 │ │ 仮想関数をオーバーライド│
└───────────┘ └─────────────┘
◇使う時
(クラスAの仮想関数を呼び出す)
┌──使われる側────┐ ┌────使う側──────┐
│ ・クラスAの仮想関数を →→→→→→・クラスAの派生クラス。 │
│ を呼び出す関数 │ │ 仮想関数をオーバーライド│
└───────────┘ └─────────────┘
『あれ、こう比べてみるとだいぶ構造が違うような……』
「ポリモーフィズムの場合、まずクラスAというものを〈使われる側〉で用
意しておく必要があります。使う側は、その派生クラスを作って、仮想関数
をオーバーライドします」
┌───── クラスA──────┐
│・仮想関数 │
└───────────────┘
△
│
│
┌───────┴───────┐
│・仮想関数(オーバーライド) │
└── クラスAの派生クラス───┘
「このオーバーライドした仮想関数が、関数ポインタの時の関数Aに当たり
ます」
『つまりこれが〈使われる側〉から呼び出されるわけね』
「もうひとつ重要な点が、使う側は〈クラスAの派生クラス〉の変数を作っ
て、そのアドレスを渡すっていう点」
『関数ポインタの時は関数のアドレス、ポリモーフィズムの時はクラスの
変数』
「実はこれが重要。関数の時には関数を渡せるだけ、つまり変数は渡せない
んです」
『そっか、関数はグローバル変数使わなきゃいけないけど、クラスの変数な
らメンバ変数で渡せる!』
「そういうこと。つまり、関数ポインタの機能をバージョンアップしたもの
がポリモーフィズム、っていうことが言えるかな」
『便利になったわけねー。複雑になったけど……』
「確かに……。さて、話を戻してインターフェイスについて」
『あーそういえば』
「上の例で言うと、前回の DoBubbleSortUseComapre() 関数が〈使われる側〉
の〈クラスAの仮想関数をを呼び出す関数〉に当たります」
// ソートを行う関数です。
void DoBubbleSortUseComapre
( int *p_piAry, int p_iSize, CComparetor *p_pcComparetor )
// CComparetor クラスの仮想関数 CompareTo() メンバ関数を呼び出します
『この第3引数に CComparetor クラスの派生クラス、つまり
CIntComparetor クラスの、変数のアドレスを渡すと、ポリモーフィズムが
効いて、オーバーライドしてる CompareTo() メンバ関数が呼び出される、
っていう仕組みね』
「そういうこと。で、ここでもう一度さっきの図を振り返ってみます」
◇準備
(派生クラスの変数のアドレスを渡す)
┌──使われる側────┐ ┌────使う側──────┐
│ ・クラスAの仮想関数を ←←←←←←・クラスAの派生クラス。 │
│ を呼び出す関数 │ │ 仮想関数をオーバーライド│
└───────────┘ └─────────────┘
『左が DoBubbleSortUseComapre() 関数、右が CIntComparetor クラスと
CompareTo() メンバ関数だね』
「この矢印の部分、右から左に CIntComparetor クラスの変数のアドレスを
渡す箇所が DoBubbleSortUseComapre() 関数の第3引数になります」
// ソートを行う関数です。
void DoBubbleSortUseComapre
( int *p_piAry, int p_iSize, CComparetor *p_pcComparetor )
↑
ここから「派生クラスの変数のアドレス」を渡します
「つまり、この第3引数が、〈呼び出してもらうメンバ関数を持つクラス〉
の変数を渡す〈受付〉になっている、というわけ」
『受付……』
「さっきの図で言うと、この受付部分が」
↓ここ
┌──使われる側────┐ ┌────使う側──────┐
│ ・クラスAの仮想関数を ←←←←←←・クラスAの派生クラス。 │
│ を呼び出す関数 │ │ 仮想関数をオーバーライド│
└───────────┘ └─────────────┘
「になります。つまり、この部分が〈使われる側〉と〈使う側〉の接続口に
なっているわけです」
『確かにここで継ながってるね』
「で、これをいきなりですがパソコンとプリンタに置き換えます」
『パソコンとプリンタ???』
┌──パソコン─────┐ ┌─プリンタ──────┐
│ ・印刷の命令←←←←←←←←←←←・印刷する機能 │
│ を行うアプリ │ │ │
└───────────┘ └───────────┘
『あ、なんか似てる』
「これって似てるでしょう。プリンタはパソコンにケーブルで継なぎます。
パソコンはプリンタに対して印刷の命令を出すことで印刷します。この時、
プリンタはどんなメーカーのどんな機種でも印刷できるでしょ?」
『うん、プリンタのアイコン押せば印刷できるもんね。あ、それって
ポリモーフィズムってこと?』
「そういうこと! つまり、あらゆるプリンタは〈プリンタの基本命令〉を
持っていて、パソコンに接続することでパソコンはその命令を送るだけで
どんなプリンタでも印刷できるわけです」
『なるほどねー、〈プリンタの基本命令〉が基本クラスの仮想関数で、それ
ぞれのプリンタの印刷機能が派生クラスでオーバーライド、ってわけね。確
かにポリモーフィズムしてる』
「で、このケーブル接続用コネクタを、専門用語で【インターフェイス】っ
て言います」
↓インターフェイス
┌──パソコン─────┐ ┌─プリンタ──────┐
│ ・印刷の命令←←←←←←←←←←←・印刷する機能 │
│ を行うアプリ │ │ │
└───────────┘ └───────────┘
『おー、つまりこのインターフェイスの部分に当たるから、基本クラスの
ことをインターフェイス、って言ってるんだ』
「そういうこと。こんな感じに、使う側と使われる側の接続部分になるのが
インターフェイス、というわけです」
『なるほどねー』
「ただし!」
『ただし?』
「全部の基本クラスがインターフェイスっていうわけじゃないんです。
インターフェイスは、次のようなクラスのことを指します」
・基本クラスは持たない(持つとしてもインターフェイスに限る)
・メンバ変数を持たない
・メンバ関数は純粋仮想関数のみ
『つまり前回の CComparetor クラスはインターフェイスってわけね』
// 比較用クラスの基本クラス。
class CComparetor
{
public:
// 比較用メンバ関数。純粋仮想関数です。
virtual bool CompareTo( int p_iL, int p_iR ) = 0;
};
『でもなんでこういうルールがあるの?』
「なぜかっていうと、中身があっちゃいけないから」
『中身?』
「パソコンとプリンタの例で言うと、インターフェイスは〈プリンタの機能〉
を持っていちゃいけない、ってこと」
『あ、なるほど。インターフェイスは接続口でプリンタじゃないから、機能
があっちゃいけないんだ』
「この CComparetor クラスの場合も、このクラスは比較機能とかは全く
持っていません。ただ、 CompareTo() メンバ関数を呼び出すための接続口
としてのみ機能します」
『だからインターフェイス、っていうわけね』
「まぁもっとも、こういうクラスをインターフェイスって呼んでいる、って
いうだけで、普通のクラスなんかと大きな違いはないんだけどね」
『それじゃ意味ないじゃん』
/*
Preview Next Story!
*/
『おー、図にしてなんとか分かってきた感じ』
「見て分かるっていうのは重要かもね」
『まぁテキストじゃ限界あるだろうけどねー』
「確かにね、アスキーアートまで行くと環境によっては見られないし」
『やっぱりメルマガじゃ限界あるんじゃない?』
「う」
『というわけで次回』
< Version 17.20 インターフェイスを戻り値にする >
「につづく!」
『さっきのプリンターとかも、あんな四角じゃいまいちだし〜』
「http://images.google.co.jp/images?q=%E3%83%97%E3%83%AA%E3%83%B3%E3%82%BFッ」
『うわ力業で来た!』