ページ 11

Global変数とStaticGlobal変数ClassStaticデータメンバの違いについて

Posted: 2011年6月09日(木) 20:00
by スモモ
皆様、お久しぶりです。
スモモです。
お世話になっております。
新しくなってから、今日は初めてです。

さっそく 、お聞きしたい事あります。

Global変数とStaticGlobal変数とClassStaticデータメンバの違い
を教えてほしいです。

Re: Global変数とStaticGlobal変数ClassStaticデータメンバの違いについて

Posted: 2011年6月09日(木) 20:32
by スモモ
追加です。

//111111111111111111111111111111111111
//xxx.h
class a
{
a();
....
};
//xxx.cpp
int b = 0;
a::a(){b++;}
//222222222222222222222222222222222222
//xxx.h
class a
{
a();
....
};
//xxx.cpp
static int b = 0;
a::a(){b++;}
//333333333333333333333333333333333333
//xxx.h
class a
{
static int b;
a();
....
};
//xxx.cpp
int a::b = 0;
a::a(){b++;}


1と2と3の違い。
ご教授の程、よろしくお願いします。

Re: Global変数とStaticGlobal変数ClassStaticデータメンバの違いについて

Posted: 2011年6月09日(木) 21:45
by dic
1と2の違い
xxx.cppで static をつけない int b を宣言、定義、使用してますが
たとえば xxxy.cpp ファイルを追加したときに効果がでてきます

xxx.cpp で
int b = 0;
xxxy.cpp で
int b = 0;
とすると2回以上定義されコンパイルエラーになります

なので
xxx.cpp で
static int b = 0;
xxxy.cpp で
static int b = 0;
とすれば、それぞれのファイルでユニークな int b が作られます




2と3の違い

2がstatic int b で xxx.cpp ファイル内で有効で
3がclass a::b で有効です
たとえば

コード:

class a
{
 static int b;
 public:
  a() { }
  a( int v ) { b = v; }
  void f() { cout << b << endl; }
};
int a::b;

void main()
{
  a  hoge( 10 );
  hoge.f();
  a  hoge2;
  hoge2.f();
}
としたら hoge::b と hoge2::b の値は同じく10になります
なかなか違いがわかる例がわかりづらいかもしれないですが
私からの説明はこうなります

Re: Global変数とStaticGlobal変数ClassStaticデータメンバの違いについて

Posted: 2011年6月09日(木) 22:19
by スモモ
dic 様

まだわかりませんが。

教えていただき、ありがとうございます。

Re: Global変数とStaticGlobal変数ClassStaticデータメンバの違いについて

Posted: 2011年6月10日(金) 00:14
by lriki
dicさんの説明を受けて、どこまでわからないのか書いていただけると有りがたいのですけど・・・(全然わからない! 1と2の違いまでは・・・ッ! etc)
とりあえず2と3に関して、例えばどんなふうに使えるのかということでアドバイスさせていただきますね。



2について・・・

例えばオープンソースのモジュールを(または他の人と共同で開発する時など)
自分のプロジェクトに組み込んでコンパイルする必要があるときに出てくる問題への対処に使います。

自分は b というグローバル変数を使いたけど、もしかしたら組み込んだモジュールの中で、
同じ名前のグローバル変数が定義されているかもしれません。
その場合は dic さんのおっしゃっているように、コンパイルエラーが出ます。
そんな不具合を避けるために、モジュール作成者が
「このグローバル変数は私が書いたソースの中だけで参照しますよ」って意味で static をつけます。



3について…

色々端折って言うと、「class a のインスタンスだけが参照できるグローバル変数」というイメージです。

例えば、class a のコンストラクタで b をインクリメント(スモモさんの貼っていただいた例ですね)し、
デストラクタでデクリメントすればclass a のインスタンスがいくつ作成されているかを知ることができます。

これを利用すれば new を使ってインスタンスの作成を行っている場合、
プログラム終了時に b の値をチェックすることで delete 忘れが無いかどうかチェックすることもできます。
(実際に全部のクラスに実装するのは大変ですけど…)


私は普段はシングルトンクラスの実装くらいにしか使いませんけど、よろしければ参考にしてみてください。

Re: Global変数とStaticGlobal変数ClassStaticデータメンバの違いについて

Posted: 2011年6月11日(土) 01:35
by スモモ
梨樹 様

教えていただき、ありがとうございます。

1と2、1と3の違いわかりました。

2と3の違いもちょっと教えていただければ、うれしいです。

//222222222222222222222222222222222222
//xxx.h
class a
{
a();
....
};
//xxx.cpp
static int b = 0;
a::a(){b++;}
//333333333333333333333333333333333333
//xxx.h
class a
{
static int b;
a();
....
};
//xxx.cpp
int a::b = 0;
a::a(){b++;}

2の StaticGlobal変数 3の ClassStaticデータメンバ 
はクラス内しか使わないなら、同じでしょうか?

ご教授の程、よろしくお願いします。

Re: Global変数とStaticGlobal変数ClassStaticデータメンバの違いについて

Posted: 2011年6月11日(土) 22:34
by lriki
例えば「b は絶対にクラス a のメンバからのみアクセスしたい」というときのアクセス制限のために使い分けます。

2の場合、xxx.cpp にクラス a 以外の関数の定義を書いていたときは
その関数からもアクセスできてしまいます。

コード:

//xxx.h
class a
{
	a();
	....
};

void add();

コード:

//xxx.cpp
static int b = 0;
a::a(){b++;}

void add(){b++;}	// class a のメンバ関数じゃないけどアクセス可能!
逆に3の場合は b を private で宣言している限り、クラス a のメンバからしかアクセスできません。


簡単ですがまとめると、

「同じソースコードの中だけでアクセスします!」というときは 2。
「クラスの中だけでアクセスします!」というときは 3。

・・・といったイメージで使い分けます。


スモモさんが個人で開発をしていて、「クラス内しか使わない」というルールを守っていれば
どちらでも大差はないと思いますが、それ以外の場合(共同開発や、他の人にレビューしてもらう等)は
アクセス範囲の制限は守っておいた方がいいと思います。

Re: Global変数とStaticGlobal変数ClassStaticデータメンバの違いについて

Posted: 2011年6月13日(月) 23:38
by スモモ
梨樹 様

教えていただき、ありがとうございます。

解決です。

dic 様、梨樹 様

お二人のおかげで、1つの問題ではなくほか問題にもわかるようになりました。本当にありがとうございました。