Version 16.25
static メンバ変数
「前回はデフォルト値とオーバーロードの違いについて説明しました」
『説明されました! って、よく考えたら今ってクラスの勉強してるんじゃ
なかったっけ?』
「う”、まぁデフォルト値はメンバ関数にも使えるし、オーバーロードとの
対比の意味もあるから」
『すっごく言い訳っぽい』
「……気を取り直して、今回は static メンバ変数というものについて説明
します」
『はーい』
「ちなみに、 static メンバ変数と static メンバ関数というものについて
説明したら、この章は終わり」
『お!』
「次の章はクラスの応用編に移ります」
『ってまたクラスかよ!』
「でもこの16章とは比べものにならないほど複雑で面白いから」
『複雑だと面白くないから!!』
「さて話を戻して、今回は static メンバ変数について説明します。
static メンバ変数はメンバ変数の一種で、クラスの変数を作らなくても元々
存在するメンバ変数です」
『?』
「例を見た方が早いかな」
// Data.h
// CDataクラス。
class CData
{
public:
// static メンバ変数。
static int m_iData;
};
// Data.cpp
#include <Windows.h>
#include <stdio.h>
#include "Data.h"
// static メンバ変数。
int CData::m_iData;
// 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::m_iData = 100;
// 出力します。
char pch[256];
sprintf( pch, "%d\n", CData::m_iData );
OutputDebugString( pch );
// 100
return 0;
}
「 CData クラスの m_iData メンバ変数が、 static メンバ変数です」
// static メンバ変数。
static int m_iData;
『お、確かに static が付いてる。……あれ? ソースファイルの方にも同
じ変数があるよ』
// static メンバ変数。
int CData::m_iData;
「そう、 static メンバ変数の場合、変数の本体をソースファイルに書く必
要があるんです」
『変数の本体!?』
「まず普通のメンバ変数は、 Version 16.02 ( No.329 ) で説明したように
クラスの変数内にメンバ変数がある、という形になります」
『うんうん』
「対して static メンバ変数は、クラスの変数内にはありません」
『じゃあどこにあるの?』
「どこと言われると難しいかも……簡単に言えば、 static メンバ変数は
グローバル変数と同じなんです」
『グローバル変数って、関数の外で宣言して、どこからでも使えるっていう
あれね』
「そうあれと同じ。 static メンバ変数は、はっきり言ってクラスとは関係
ない変数です。一応クラスのメンバではあるんだけど、クラスの変数とは
関係なく、ただひとつだけ存在する変数です」
『この例だと m_iData がその static メンバ変数ってわけね』
「 static メンバ変数は、以下のように【クラス名::メンバ変数名】で
アクセスします」
// static メンバ変数を使用します。
CData::m_iData = 100;
『なるほど、これがクラスの変数が必要ない、ってことね』
「そういうこと。普通のメンバ変数なら、 CData クラスの変数、たとえば
cData を作って、【cData.m_iData = 100;】みたいにするところなんだけ
ど」
『 static メンバ変数は、そのクラスの変数が必要ない、と』
「逆に言えばクラスでひとつの共有物だから」
『そか、クラスの変数をいくら作っても、 static 変数はひとつだけ
なんだ』
「そういうこと。特に、メンバ関数から使う時には気を付けた方がいいかな」
『どゆこと?』
「 static メンバ変数は、以下のように普通のメンバ関数から使用すること
もできます」
// Data.h
// CDataクラス。
class CData
{
public:
// static メンバ変数。
static int m_iData;
// static メンバ変数を使用するメンバ関数。
void UseData();
};
// Data.cpp
#include <Windows.h>
#include <stdio.h>
#include "Data.h"
// static メンバ変数。
int CData::m_iData;
// Main.cpp
#include <Windows.h>
#include <stdio.h>
#include "Data.h"
// static メンバ変数を使用するメンバ関数。
void CData::UseData()
{
// 1増やします。
++m_iData;
}
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
// static メンバ変数を使用します。
CData::m_iData = 100;
// 普通のメンバ変数を使用します。
CData cData;
cData.UseData();
// もうひとつCDataクラスの変数を作って、
// 普通のメンバ変数を使用します。
CData cData2;
cData2.UseData();
// 出力します。
char pch[256];
sprintf( pch, "%d\n", CData::m_iData );
OutputDebugString( pch );
// 102
return 0;
}
「メンバ関数から使用する時には、クラス名を付けず、直接メンバ変数名を
指定することができます」
// static メンバ変数を使用するメンバ関数。
void CData::UseData()
{
// 1増やします。
++m_iData;
}
『ちょいまち!! これじゃ普通のメンバ変数とかわんないじゃん!』
「そう、メンバ関数内から static メンバ変数へは、普通にアクセスできる
んです。ただ、やっぱりクラスに1つだけだから」
『あー、だから結果が 102 、 2 も増えてるんだ』
「そういうこと」
// static メンバ変数を使用します。
CData::m_iData = 100; // ← 100
// 普通のメンバ変数を使用します。
CData cData;
cData.UseData(); // ← 101
// もうひとつCDataクラスの変数を作って、
// 普通のメンバ変数を使用します。
CData cData2;
cData2.UseData(); // ← 102
『 CData クラスの変数が違っても、同じ m_iData を増やしてるってるから
2 増えるわけね』
「そういう意味で使うのが危険だから、あまり作らない方がいいかも」
/*
Preview Next Story!
*/
『んー、そうよね、グローバル変数と同じだよね』
「どうしたの?」
『なんかメンバ変数に慣れすぎて、 static メンバ変数の方が難しいかも』
「いい兆候かも」
『なんかすごーく嫌な予感がする』
「というわけで次回」
< Version 16.26 static メンバ関数 >
『につづく!』
「この次の章は本当に楽しいから期待していて」
『なんかすっごくヤバい気がする』