- ベストアンサー
C++クラスのstaticの違い
- (1)クラスのメンバー変数にstaticを付けた場合と、メンバーではない変数にstaticを付けた場合の違いは何ですか?
- (2)クラスのメンバー関数にstaticを付けた場合と、メンバーではない関数にstaticを付けた場合の違いは何ですか?
- C++のクラスにおけるstaticの使い方について理解したいです。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
3)クラスにおける static これは、アクセス制御ではなく、「クラスのインスタンス全体での共有」を行うためのもです。 アクセス制御ではないので、static をつけただけで、クラスの外からでも参照できると言うことはありません。 あくまでも、宣言された位置が、public: か、private: か、proteced: かで、どの範囲から参照できるかが決まります。 さて、クラスというのは、通常、インスタンスを生成して使用します。 class CAT; に対して、 CAT tama("nya"); CAT buchi("myamya"); とか。 こことで(正しく設計されていれば) tama が、buchi の泣き方を知ることはありません。 これが、「情報の隠蔽」という機能で、クラスの利点のひとつにもなっています。 一方で、これだけでは、たとえば、「では、CAT は何匹存在するのだろうか?」という情報を得ることはできません。 tama にしても、buchi にしても、自分自身の情報は知っていますが、CAT というクラス全体の情報は何も知らないからです。 これを解決するために使うのが、class における static 指定です。 class CAT { private: char *myNakigoe; static int number; public: CAT(char *nakigoe) : myNakigoe(nakigoe) { numer ++; } ~CAT() { number--;} // このmyNakigoe の初期化は、本当はちょっと危険 }; などとしておけば、クラスの中から、CAT::number を参照すれば、現存する猫の数がわかります。 メンバ関数に対する static 指定も同じで、「クラス全体の情報を知る/操作する」ための関数は、static をつけて指定します。 たとえば、 static void defaultNakigoe(char *); などで、泣き方を指定しない猫たち全部のデフォルトの鳴き声を指定できたりします。 この場合、あくまでも、鳴き声を指定しない猫たち「全部」なので、個別の猫の情報には直接タッチしないことに注意してください。 ただ、static なメンバ関数から、個々のインスタンスの情報が絶対にアクセスできないというわけではありません。 static char *nakigoe(CAT *dare) { return dare->myNakigoe; } などと言うこともできなくはありません。
その他の回答 (2)
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
static という予約後は、実は、いろいろな意味に使い回されています。 これがそもそも混乱の元になっているわけですが、クラスに関連するもの、しないものをふくめて、こういう意味があります。 1)関数の(ブロックの)中で定義される変数。 void count() { int n = 0; n++; std::cout << "cout = " << n << "\n"; } この関数は、何度呼び出しても、毎回 count = 0 を表示します。 これは、n という変数が、関数の呼び出しごとに生成・初期化されるからです。 一方、 void count() { static int n = 0; n++; std::cout << "cout = " << n << "\n"; } とすると、この関数は、呼び出された回数を表示するようになります。 static をつけたことで、n が、「プログラムの実行の最初に生成・初期化されて、その変数が消えずに残る」からです。 この場合、最初の(static をつけない)変数は、auto int n = 0; と書きますが、特に断りがない限りCの変数は auto なので、auto が明示されることはほぼありません。 ※ただし、 static int n = 0; と書けば「初期化」なので、プログラム実行時に1回しか初期化されませんが、 static int n; n = 0; と書けば、 n = 0; は、当然、関数の呼び出しごとに実行されてしまいます。 2)ブロックの外の変数および、関数 これは、 int n; int main() { .... } のように、(main を含む)関数の外に定義される変数です。 1)で、「static をつけると、プログラム実行時に1度だけ初期化され、その変数が消えずに残る」と書きましたが、ブロックの外にある変数はもともと、「プログラム実行中消えずに残る」ものです。 ですから、ブロックの中にある static とは意味が違います。 こちらは、「アクセス制御」のためのものです。 ブロックの外にある変数は、「グローバル変数」と呼ばれ、そのファイルの中にある関数で共有されます。 それだけではなく、別のファイルの中にある関数とも共有されてしまいます。 もともと「変数の共有」というのはできるだけ避けるべきです。 それは、あちこちで共有されてしまえば、何かおかしな事が起こったときに、どこでおかしな事になったのか、突き止めるのが大変だからです。 そのため、「同じファイルの中の各関数では共有したいけど、このファイルの中だけの共有に抑えたい」という要求があります。 これを実現するのが、ブロックの外にある変数での static 指定です。 static int n; int main() { .... } こうすれば、この n は、この他のファイルからは参照できなくなります。 ブロックの外にある「関数」も、static をつける意味は同じです。 このファイルの中からしか参照できないようにするには、 static void func(); のように、static をつけます。 関数の場合、もともと共有するものという性格が強いのですが、「他のファイルから参照できない」ということを保証することで、関数の仕様変更を行う際、「そのファイルの中での使われ方」だけを考えれば良いという効果があります。 ここであげた、「ブロックの外のstatic」は、アクセス制御に関わるものですから、C++であれば、クラスや、name space を使う事で、目的を果たすこともできます。 しかし、C言語で、「クラスもname space もない」という状況で導入されたまま、互換性維持のためにそのまま残っているわけです。 3)クラス定義における static …… 続く。
- anmochi
- ベストアンサー率65% (1332/2045)
簡単な解説をすると以下のようになります。 [プログラム例] class MyClass { public: static int internalCount; ・・・(1) static void func(MyClass& a) {/* ... */} ・・・(2) }; static int i; ・・・(3) static void f(MyClass& a) ・・・(4) { /* ... */ } (1)クラス内のstatic変数:クラス変数という(staticをつけない変数はインスタンス変数という)。MyClassクラスのインスタンス全てで共有される変数。MyClass::internalCount = 0という風に(publicなので)クラス外からのアクセスも可能。 (2)クラス内のstatic関数:MyClassのインスタンス->func()ではなく、MyClass::func()という風にインスタンスを作らなくても呼び出せる関数。クラス変数にはアクセスできるがインスタンス変数にはアクセスできない。 (3)クラス外のstatic変数:C言語のstaticと同じ。これ以外のソースファイル中にextern int i;宣言があってもこの変数はこのソースファイル固有。 (4)クラス外のstatic関数:C言語のstaticと同じ。これ以外のソースファイル中でf()を呼び出そうとしても呼び出せない。 (3)と(4)はC言語の概念なので(C++言語に関する内容に言及しない)C言語の教科書を参照した方が良いでしょう。
お礼
ありがとうございます。 何が違うのかはっきりしてすっきりしました。