#pragma twice

KAB-studio > プログラミング > #pragma twice > 354 Version 16.27 static と this

#pragma twice 354 Version 16.27 static と this

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

 Version 16.27
static と this

「前回は static メンバ関数について説明しました」
『 static メンバ変数と static メンバ関数、どっちもクラスの変数を作ら
なくても使うことができるんだよね』
「そう、それが普通のメンバ変数、メンバ関数との違い」
『でも、 static な方から普通の方って使えないんだよね』

・static メンバ関数→→→×→→→  普通のメンバ変数、 普通のメンバ関数
・ 普通のメンバ関数→→→○→→→ static メンバ変数、static メンバ関数

『これがちょっと不便だよね』
「でも、ちゃんとした理由があるんです。なぜこうなるのか、まず仕組みで
考えてみます」
『はーい』
「まず、普通のメンバ関数は置いといて、普通のメンバ変数に絞って考えた
方が分かりやすいかな」
『普通なメンバ変数、つまり非 static メンバ変数ってことね』
「普通のメンバ変数やメンバ関数を使うためには、クラスの変数が必要で
す。特にメンバ変数の方は、クラスの変数の中に置かれる形になるから」
『 Version 16.02 ( No.329 ) で言ってたね、メンバ変数がそのクラスの
変数の中身になる、ってことなんだよね』
「そういうこと。だから、普通のメンバ変数はそのクラスの変数が必要不可
欠です。さて、この普通のメンバ変数を、 static メンバ関数から使用する
場合を考えてみます」
『 static メンバ関数は、クラスの変数がなくても呼び出せる……そか、 
static メンバ関数から普通のメンバ変数にアクセスするためには、その
メンバ変数が入っている、クラスの変数が必要、でも』
「 static メンバ関数を呼び出す時にははクラスの変数がないわけだから」
『そのメンバ変数が入ってるクラスの変数が分からない! ってこと?』
「そういうこと。 static メンバ関数は、クラスの変数とは関係なく呼び出
せるわけだから、そのクラスの変数に入っているメンバ変数とも関係ない
わけです」
『なるほど……んー、でももうちょっと欲しいかも、なんかが』
「じゃあ別の視点から考えてみようか。 this ポインタって憶えてる?」
『 Version 16.03 ( No.330 ) で教わったね、自分の変数のポインタで、隠
された引数……あ!! そっか、 static メンバ関数って、 this ポインタ
がないんだ!』
「そう!  static メンバ関数は、クラスの変数を持たずに呼び出すから、
普通のメンバ関数が【呼び出したときに後ろで渡される、クラスの変数の
ポインタ】つまり this ポインタが渡されないんです」
『メンバ関数からメンバ変数使う時は、 this->m_iData みたいに this 
ポインタ使うのと同じ、ってことだったから、その this ポインタがない 
static メンバ関数は、メンバ変数にアクセスできない!』
「というわけです。これをプログラムで確認してみようか。 CData クラス
に、普通のメンバ変数 m_iNonStaticMember 、普通のメンバ関数
NonStaticMember() 、 static メンバ関数 StaticMember() を持たせます」

// Data.h

// CDataクラス。
class CData
{
public:
    // 非 static メンバ変数。
    int m_iNonStaticMember;

    // static メンバ関数。
    static void StaticMember();
    // 非 static メンバ関数。
    void NonStaticMember();
};


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

#include "Data.h"

// static メンバ関数。
void CData::StaticMember()
{
    // this->m_iNonStaticMember = 100;
}

// 非 static メンバ関数。
void CData::NonStaticMember()
{
    this->m_iNonStaticMember = 100;
}


// 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
    )
{
    // static メンバ関数を使用します。
    CData::StaticMember();
    // 非 static メンバ関数を使用します。
    CData cData;
    cData.NonStaticMember();

    return 0;
}

「 NonStaticMember() メンバ関数は、 cData のアドレスを this ポインタ
として受け取ります」

      →→→→→→→→→→↓
      ↑                  ↓
    cData.NonStaticMember(↓);
                          ↓
                          →↓
                            ↓
void CData::NonStaticMember(↓)
{                           ↓
       ←←←←←←←←←←←
      ↓
    this->m_iNonStaticMember = 100; 
}

「 NonStaticMember() メンバ関数は、 cData のアドレスを this ポインタ
として受け取るため、 this ポインタを通して普通のメンバ変数やメンバ関数
を使うことができるわけです」
『でも、 StaticMember() メンバ関数は、この this ポインタを受け取らな
い』
「クラスの変数を作っていないから、渡しようがないんです」

    // static メンバ関数を使用します。
    CData::StaticMember();

// static メンバ関数。
void CData::StaticMember()
{
    // this ポインタがないから非 static メンバ変数には
    // アクセスできません。
    // this->m_iNonStaticMember = 100;
}

「 StaticMember() メンバ関数を呼び出す時に CData クラスの変数を必要
としないので、そのアドレスを持つ this ポインタも渡されないわけです」
『普通のメンバ変数を使うためには this ポインタが必要だから、アクセス
できないってわけね』
「そういうこと」
『……んー、普通のメンバ変数はこれでわかったけど、普通のメンバ関数を 
static メンバ関数から呼び出せないのってなんで?』
「同じように考えればわかると思うよ。普通のメンバ関数を呼び出すときに
裏で渡されるのは?」
『クラスの変数のアドレスが入った this ポインタ』
「それを static メンバ関数は」
『持ってない!』
「そういうこと」

// static メンバ関数。
void CData::StaticMember()
{
    // 非 static メンバ関数を呼びたいけど呼べません。
    // 渡さなきゃいけない this ポインタがないから。
    // NonStaticMember( this );
}

「普通のメンバ関数は、中で普通のメンバ変数にアクセスするために this 
ポインタが必要になるので、必ず渡す必要があります」
『でも static メンバ関数はそれを持ってない、渡せない、だから呼び出せ
ない』
「そういうこと。こんなふうに、 this を中心に考えると分かりやすいか
な」
『うん、なんとなく分かったかも』
「もう一度まとめると、以下のようになります」

・static メンバ関数→→→×→→→  普通のメンバ変数、 普通のメンバ関数
・ 普通のメンバ関数→→→○→→→ static メンバ変数、static メンバ関数

『つまり static メンバ関数から普通のメンバは使えない、 this ポインタ
がないからアクセスできないってわけね』
「そういうこと」
『でもさ、それってすごく不便じゃない? 普通にクラスの変数作って普通
にメンバ関数呼び出せばいいんだから、 static メンバ関数とか作る意味な
いじゃん』
「でも実は使い道があるんです。というわけで次回に続く!」

/*
    Preview Next Story!
*/
『不便! 使いづらい! 不便!』
「でもWin32 APIを使う時には便利なんです」
『 static メンバ変数が?』
「ううん、 static メンバ関数が」
『というわけで次回』
< Version 16.28 関数の代わりに static メンバ関数 >
「につづく!」
『 static メンバ変数は?』
「えーっと……」
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。