#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のトップページをご覧ください。