Staticキーワードについて
C++のstaticには,プロセスプログラミングにおけるstaticとオブジェクトプログラミングにおけるstaticの2つの使い方がある.前者は普通の変数と関数に適用され、クラスには関与しない.後者は主にstaticのクラスにおける役割を説明する.
一、プロセス設計におけるstatic向け
1、静的グローバル変数
グローバル変数の前にキーワードstaticを付けると、この変数は静的グローバル変数として定義されます.静的グローバル変数の例を次に示します.
//Example 1
#include <iostream.h>
void fn();
static int n; //
void main()
{
n=20;
cout<<n<<endl;
fn();
}
void fn()
{
n++;
cout<<n<<endl;
}
静的グローバル変数には、次のような特徴があります.静的変数は、後述する静的ローカル変数を含むグローバルデータ領域にメモリを割り当てます.完全なプログラムの場合、メモリ内の分散は次の図のようになります.
コード領域
グローバルデータ領域
スタックゾーン
スタック領域
一般プログラムのnewによって生成された動的データはスタック領域に格納され,関数内部の自動変数はスタック領域に格納される.自動変数は一般に関数の終了に伴って空間を解放し、静的データ(関数内部の静的局所変数であっても)はグローバルデータ領域に格納される.グローバルデータ領域のデータは関数の終了によって空間を解放するわけではない.注意深い読者はExample 1のコードに
static int n; //
から int n; //
プログラムは正常に動作します.確かに、グローバル変数を定義すると、ファイル内の変数の共有が可能になりますが、静的グローバル変数を定義するには、次のメリットがあります.
上記のサンプルコードを次のように変更できます.
//Example 2
//File1
#include <iostream.h>
void fn();
static int n; //
void main()
{
n=20;
cout<<n<<endl;
fn();
}
//File2
#include <iostream.h>
extern int n;
void fn()
{
n++;
cout<<n<<endl;
}
Example 2をコンパイルして実行すると、上記のコードはそれぞれコンパイルできますが、実行時にエラーが発生します.試しにstatic int n; //
からint n; //
実行プログラムを再コンパイルし、グローバル変数と静的グローバル変数の違いを注意深く理解します.2、静的局所変数
ローカル変数の前にキーワードstaticを付けると、この変数は静的ローカル変数として定義されます.
静的局所変数の例を次に示します.
//Example 3
#include <iostream.h>
void fn();
void main()
{
fn();
fn();
fn();
}
void fn()
{
static n=10;
cout<<n<<endl;
n++;
}
は、通常、プログラムが文を実行するたびにローカル変数にスタックメモリを割り当てる変数を関数内で定義します.しかし、プログラムが関数体を終了するにつれて、システムはスタックメモリを回収し、ローカル変数もそれに応じて失効します.しかし、2回の呼び出しの間に変数の値を保存する必要がある場合があります.一般的な考え方は、グローバル変数を定義して実現することです.しかし,これにより変数は関数そのものに属さず,関数のみの制御を受けず,プログラムのメンテナンスに不便をもたらす.
静的局所変数はちょうどこの問題を解決できる.静的ローカル変数は、スタックに保存するのではなく、グローバルデータ領域に保存され、次回の値が付与されるまで、毎回の値は次の呼び出しに維持されます.
静的ローカル変数には、次のような特徴があります.
3、静的関数
関数の戻りタイプにstaticキーを付けると、関数は静的関数として定義されます.静的関数は通常の関数とは異なり、宣言されたファイルでのみ表示され、他のファイルでは使用できません.
静的関数の例:
//Example 4
#include <iostream.h>
static void fn();//
void main()
{
fn();
}
void fn()//
{
int n=10;
cout<<n<<endl;
}
静的関数の利点を定義します.二、オブジェクト向けstaticキーワード(クラス内のstaticキーワード)
1、静的データメンバー
クラス内のデータ・メンバーの宣言にキーワードstaticを追加します.このデータ・メンバーは、クラス内の静的データ・メンバーです.まず、静的データ・メンバーの例を挙げます.
//Example 5
#include <iostream.h>
class Myclass
{
public:
Myclass(int a,int b,int c);
void GetSum();
private:
int a,b,c;
static int Sum;//
};
int Myclass::Sum=0;//
Myclass::Myclass(int a,int b,int c)
{
this->a=a;
this->b=b;
this->c=c;
Sum+=a+b+c;
}
void Myclass::GetSum()
{
cout<<"Sum="<<Sum<<endl;
}
void main()
{
Myclass M(1,2,3);
M.GetSum();
Myclass N(4,5,6);
N.GetSum();
M.GetSum();
}
では、静的データ・メンバーには次のような特徴があります.2、静的メンバー関数
静的データ・メンバーと同様に、クラスの特定のオブジェクトにサービスするのではなく、クラスのすべてのサービスに対する静的メンバー関数を作成することもできます.静的メンバー関数は、静的データメンバーと同様にクラスの内部実装であり、クラス定義の一部に属します.通常のメンバー関数には、通常のメンバー関数が常にクラスの特定のオブジェクトに属するため、thisポインタが隠されています.通常、thisはデフォルトです.関数fn()のように実際にはthis->fn()です.しかし、通常の関数と比較すると、静的メンバー関数は任意のオブジェクトに関連付けられていないため、thisポインタはありません.この意味では、クラスオブジェクトに属する非静的データ・メンバーにも非静的メンバー関数にもアクセスできません.残りの静的メンバー関数のみを呼び出すことができます.次に、静的メンバー関数の例を示します.
//Example 6
#include <iostream.h>
class Myclass
{
public:
Myclass(int a,int b,int c);
static void GetSum();/
private:
int a,b,c;
static int Sum;//
};
int Myclass::Sum=0;//
Myclass::Myclass(int a,int b,int c)
{
this->a=a;
this->b=b;
this->c=c;
Sum+=a+b+c; //
}
void Myclass::GetSum() //
{
// cout<<a<<endl; // ,a
cout<<"Sum="<<Sum<<endl;
}
void main()
{
Myclass M(1,2,3);
M.GetSum();
Myclass N(4,5,6);
N.GetSum();
Myclass::GetSum();
}
静的メンバー関数については、次の点にまとめることができます.