#pragma twice

KAB-studio > プログラミング > #pragma twice > 372 Version 17.17 関数ポインタの代わりとしてのポリモーフィズム

#pragma twice 372 Version 17.17 関数ポインタの代わりとしてのポリモーフィズム

前のページへ 表紙・目次へ 次のページへ

 Version 17.17
関数ポインタの代わりとしてのポリモーフィズム

前回は純粋仮想関数と抽象クラスについて説明しました
んーでもやっぱり目的がいまいちわかんないかも?
というわけで、抽象クラス、というかポリモーフィズムの具体的な使用例
を今回は説明します。比較的分かりやすいのが、関数ポインタとして使うこ
とかな
関数ポインタって、関数のアドレスを入れる変数だよね
そう、 Version 13.01 ( No.237 ) や Version 13.17 ( No.253 ) で説明
した、関数のアドレスを格納する変数のこと
あれと同じような使い方ができるの?
そう。ちょうど Version 13.17 ( No.253 ) で使用している qsort() 関数
の比較用関数みたいにね。実際に今回は、ソートの比較用関数を抽象クラス
で実現してみます
おー、なんか今回は実践的
まず、ベースは Version 13.09 ( No.245 ) の、 CompareTo() 関数と
DoBubbleSortUseComapre() 関数の組み合わせを利用します
これをポリモーフィズムに置き換える、と
そういうこと。今回は、まず完成品のプログラムから

// Main.cpp
#include <Windows.h>
#include <stdio.h>

// 比較用クラスの基本クラス。
class CComparetor
{
public:
    // 比較用メンバ関数。純粋仮想関数です。
    virtual bool CompareTo( int p_iL, int p_iR ) = 0;
};

// 実際の比較用クラスです。
// 整数値を昇順でソートするよう比較します。
class CIntComparetor : public CComparetor
{
public:
    // 比較用メンバ関数。
    // p_iL > p_iR なら true を、
    // それ以外は false を返すようにしてください。
    bool CompareTo( int p_iL, int p_iR )
    {
        if( p_iL > p_iR )
        {
            return true;
        }

        return false;
    }
};

// 実際の比較用クラスです。
// 整数値を降順でソートするよう比較します。
class CIntDescComparetor : public CComparetor
{
public:
    // 比較用メンバ関数。
    // p_iL < p_iR なら true を、
    // それ以外は false を返すようにしてください。
    bool CompareTo( int p_iL, int p_iR )
    {
        if( p_iL < p_iR )
        {
            return true;
        }

        return false;
    }
};

// ソートを行う関数です。
void DoBubbleSortUseComapre
    ( int *p_piAry, int p_iSize, CComparetor *p_pcComparetor )
{
    // 入れ替え先のループです。
    for( int iOut = 0; iOut < p_iSize - 1; iOut++ )
    {
        // 最後から先頭方向へのループです。
        // ただし入れ替え先までです。
        for( int iIn = p_iSize - 1; iOut < iIn; iIn-- )
        {
            if( p_pcComparetor->CompareTo
                    ( p_piAry[iIn - 1], p_piAry[iIn] ) == true )
            {
                // 前の方が大きいので入れ替えます。
                int iTemp = p_piAry[iIn];
                p_piAry[iIn] = p_piAry[iIn - 1];
                p_piAry[iIn - 1] = iTemp;
            }
        }
    }
}

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    int iAry[5];
    iAry[0] = 4;
    iAry[1] = 9;
    iAry[2] = 3;
    iAry[3] = 5;
    iAry[4] = 8;

    // 比較用クラスの変数を用意します(昇順)。
    CIntComparetor cIntComparetor;

    // ソートします。
    DoBubbleSortUseComapre( iAry, 5, &cIntComparetor );

    for( int iF1 = 0; iF1 < 5; ++iF1 )
    {
        char pch[256];
        sprintf( pch, "%d ", iAry[iF1] );
        OutputDebugString( pch );
    }
    OutputDebugString( "\n" );
    // 3 4 5 8 9 

    // 比較用クラスの変数を用意します(降順)。
    CIntDescComparetor cIntDescComparetor;

    // ソートします。
    DoBubbleSortUseComapre( iAry, 5, &cIntDescComparetor );

    for( iF1 = 0; iF1 < 5; ++iF1 )
    {
        char pch[256];
        sprintf( pch, "%d ", iAry[iF1] );
        OutputDebugString( pch );
    }
    OutputDebugString( "\n" );
    // 9 8 5 4 3 

    return 0;
}

長!
新しいクラス使うこともあって複雑になりそうだったから、 Main.cpp に
まとめてあります
おー、メンバ関数もインラインになっててちょっと見やすいかも
まずクラス構造は以下のようになっています

                ┌───────────┐
                │CComparetor クラス    │
                └───────────┘
                            △
                            │
            ┌───────┴───────┐
            │                              │
┌─────┴─────┐    ┌──────┴──────┐
│CIntComparetor クラス │    │CIntDescComparetor クラス │
└───────────┘    └─────────────┘

 CComparetor クラスには純粋仮想関数 CompareTo() メンバ関数がありま
す。ソートを行う DoBubbleSortUseComapre() では、このメンバ関数を呼び
出して比較を行います

// ソートを行う関数です。
void DoBubbleSortUseComapre
    ( int *p_piAry, int p_iSize, CComparetor *p_pcComparetor )
{                                                  ↓
// ...                                             ↓
            if( p_pcComparetor->CompareTo ←←←←←
                    ( p_piAry[iIn - 1], p_piAry[iIn] ) == true )
// ...
}

この DoBubbleSortUseComapre() 関数は、元のプログラムのこの比較箇所
だけ変更してあります。それ以外は同じということを確認してください
前回と同じ、基本クラスのポインタを使って純粋仮想関数を呼び出すわけ
ね。で、実際に呼び出されるのは、オーバーライドして定義を作っている、
派生クラスの方ってことね
そういうこと。実際に呼び出されるのは CIntComparetor クラスと
CIntDescComparetor クラスの CompareTo() メンバ関数です
このメンバ関数の中身も、元のプログラムの CompareTo() 関数と同じね。
CIntComparetor クラスと CIntDescComparetor クラスの違いは?
昇順と降順。 CIntDescComparetor クラスの方は【<】が【>】になってる
から
 Version 13.08 ( No.244 ) の話ね
で、こうすることで、どちらのクラスを渡すかによって昇順と降順が切り
替わるようになります

    // 比較用クラスの変数を用意します(昇順)。
    CIntComparetor cIntComparetor; →→→→→
                                            ↓
    // ソートします。                       ↓
    DoBubbleSortUseComapre( iAry, 5, &cIntComparetor );
    // 3 4 5 8 9 ←昇順
// ...
    // 比較用クラスの変数を用意します(降順)。
    CIntDescComparetor cIntDescComparetor;  →→→
                                                 ↓
    // ソートします。                            ↓
    DoBubbleSortUseComapre( iAry, 5, &cIntDescComparetor );
    // 9 8 5 4 3 ←降順

おお、ちゃんと切り替わってる!
と、ちょっと早足すぎたから次回も引き続き

/*
    Preview Next Story!
*/
この辺が良く使われる方法かな
なんかやっと見えてきたかも
ま、それも基本的な仕組みが解っているからなんだけどね
む、そういうもの?
そういうもの
というわけで次回
< Version 17.18 インターフェイスという考え方 >
につづく!
いつも通り具体例先の方が良かった気がするけど
ポリモーフィズムだけは逆がいいかな、って
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。