#pragma twice

KAB-studio > プログラミング > #pragma twice > 355 Version 16.28 関数の代わりに static メンバ関数

#pragma twice 355 Version 16.28 関数の代わりに static メンバ関数

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

 Version 16.28
関数の代わりに static メンバ関数

前回は static メンバ関数について説明しました
なーんか不便だったけど
うん、 static メンバ関数は変数を通して呼び出す必要がないから、同じ
クラスの非 static メンバにアクセスできないからね
そこがめんどいんだよねー。で、今回はその使い道の話だよね
そう。 static メンバ関数の目的は、ずばり

・普通の関数の代わり

に使います
……普通の関数の代わり?
そう、つまりメンバ関数ではない、普通の関数。特によく使うのが

・コールバック関数の代わり

という使い道です
コールバック関数ってなんだっけ
関数ポインタを渡しておくことで、あとでその関数を呼び出してもらう、
そういう関数のこと。たとえばウィンドウプロシージャとか
あ、そういう関数ね
別に普通の関数でもいいんだけど、でも〈あるクラスと結び付けたい〉、
そういう場合にはこの static メンバ関数を使用します
んー、で、具体的にはどうつかうの?
そうだね……スレッドを例にしようか
スレッドって、もうひとつプログラムの流れを作るっていうあれだよね
 Version 14.14 ( No.281 ) と Version 14.15 ( No.282 ) で作成方法と
使用方法を説明したよね。これと同じことを、 static メンバ関数でも行い
ます
そんなことできるんだ……
まず、これからのプログラムを試す前に設定を変更します。メニューの
【プロジェクト】-【設定】を選択してください
おなじみのダイアログね。このどこ変えるの?
【C/C++】-【コード生成】の【使用するランタイム ライブラリ】を
次のいずれかに変更してください

[デバッグビルド]
・マルチスレッド(デバッグ)
・マルチスレッド(DLL、デバッグ)

[リリースビルド]
・マルチスレッド
・マルチスレッド(DLL)

あ、これって Version 15.22 ( No.322 ) のだね
そう。これが【シングルスレッド】になっていたら、【マルチスレッド】
のバージョンに変えておいてください
ほい
それでは、今度はプログラムの方

// Data.h

// CDataクラス。
class CData
{
public:
    // static メンバ関数。
    // このメンバ関数が新しいスレッドから呼び出されます。
    void static __cdecl ThreadFunction( void *p_p );
};


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

#include "Data.h"

// static メンバ関数。
// このメンバ関数が新しいスレッドから呼び出されます。
void __cdecl CData::ThreadFunction( void *p_p )
{
    OutputDebugString( "スレッドから。\n" );
}


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

#include "Data.h"

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    // 新しいスレッドを作って、CDataクラスの
    // ThreadFunction()メンバ関数を呼び出します。
    _beginthread( CData::ThreadFunction, 0, NULL );

    OutputDebugString( "スレッド呼んだよ。\n" );
    OutputDebugString( "5 秒止まります。\n" );
    Sleep( 5 * 1000 );
    OutputDebugString( "5 秒止まりました。\n" );
    OutputDebugString( "関数終了します。\n" );

    return 0;
}

お、マルチスレッドの関数が
基本的には Version 14.14 ( No.281 ) と同じです。そのときは以下のよ
うに使用していました

// 別スレッドで呼び出される関数。
void __cdecl ThreadFunction( void *p_p )
{
    TRACE( "スレッドから。\n" );
}

// スレッドを作って呼び出す関数。
void UseThread()
{
    _beginthread( ThreadFunction, 0, NULL );
}

 _beginthread() がスレッド作って呼び出すランタイムで、 
ThreadFunction() がその呼び出される関数なんだよね
そういうこと。今回もその関係と同じ。新しいスレッドで呼び出す関数を
static メンバ関数にします

class CData
{
public:
    // static メンバ関数。
    // このメンバ関数が新しいスレッドから呼び出されます。
    void static __cdecl ThreadFunction( void *p_p );
};

そか、さっきの ThreadFunction() をメンバ関数にして、 static 付けれ
ばいいんだ
 static を付ける場所に注意してね。戻り値の次、って憶えておくといい
かも
はーい
で、このように static メンバ関数としておけば、 _beginthread() 等の
関数に関数ポインタを渡すことができます


    // 新しいスレッドを作って、CDataクラスの
    // ThreadFunction()メンバ関数を呼び出します。
    _beginthread( CData::ThreadFunction, 0, NULL );


あ、書き方は CData::ThreadFunction なんだ
そう、関数のアドレスを取得するわけだから()は付けないようにします。
あとは、他の static メンバ関数と同じようにクラス名の【CData::】を付
け加えておきます
これで static メンバ関数が呼び出されるんだ……
ちなみに当然だけど、非 static メンバ関数だとエラーになります

// CDataクラス。
class CData
{
public:
    // static メンバ関数。
    void __cdecl ThreadFunction( void *p_p );
//      ↑static がありません。
    // コンパイルエラー:
    // error C2664: '_beginthread' : 
    // 1 番目の引数を 
    // 'void (__cdecl CData::*)(void *)' から 
    // 'void (__cdecl *)(void *)' に変換できません。
};

やっぱだめなんだね
非 static メンバ関数は、必ず変数と結び付けて呼び出すことになるか
ら。関数ポインタだけ渡すようだとその変数を渡す方法がないからね
だから static メンバ関数にする、ってわけね
さて、実は今回で Version 16 は終了です
ええっ!? なんかすごく中途半端なところで終わるような……
そのとおり。なぜかというと、次の Version 17 も引き続きクラスの解説
だから
……ってことは、あまり内容は変わらない?
クラスの解説、っていう点では変わらないけど、でも内容的にはかなり違
うかも。とりあえず……
とりあえず?
面白いと思うよ
まっさかー

/*
    Preview Next Story!
*/
あり得ない! 面白いとかあり得ないから!
プログラミングは楽しくない?
それはおいといて!
置いとくのか
というわけで次回
< Version 17.01 クラスの継承 >
につづく!
継承?
そう、全てはここから始まるんです
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。