PHPにおける静的キーワードの役割

黄舟
リリース: 2023-03-12 11:56:01
オリジナル
8786 人が閲覧しました

次の記事の要約:

1. 静的変数の場合: ローカライズ (名前の競合)、初期化 = 0、一意の共有 (静的領域)。特に、クラスの静的メンバー変数の場合: (1) クラス全体に属し、インスタンスを介する代わりにクラス名を介して直接アクセスできます。 (2) 初期化され、クラス内で static として宣言され、クラスの外部で初期化される必要があります (static追加することはできません)

2 .クラスの静的メンバー関数の場合、(1) this ポインターはなく、静的メンバー変数と静的メンバー関数のみにアクセスでき、仮想関数として宣言することはできません (2) のサブクラスでよく使用されます。マルチスレッド。

------------------------------------------------ -------------------------------------------------- --------------------------------------------------

1. static とは何ですか?
static は、C++ で変数の保存方法と可視性を制御するために使用されます。 S 2. 静的変数で定義された変数を導入するのはなぜですか? プログラムがその定義に従って実行されると、コンパイラーはスタック上に関数によって割り当てられたスペースを関数上で実行することを誰もが知っています。実行 最後に解放されますが、次の呼び出しまで関数内のこの変数の値を保存したい場合、どうすればそれを実現できるでしょうか?という疑問が生じます。 最も簡単に考えられる方法は、グローバル変数を定義することですが、グローバル変数として定義すると多くの欠点があります。最も明らかな欠点は、この変数のアクセス スコープが破壊されることです (この関数で定義された変数が制御されるだけではなくなります)。この機能)。

3. static を使用するのはどのような場合ですか?
特定のオブジェクトではなくクラス全体にサービスを提供するデータ オブジェクトが必要であり、同時にクラスのカプセル化を破壊しないようにする必要があります。つまり、このメンバーはクラス内に隠蔽され、外の世界には見えません。

4. 静的の内部メカニズム:
静的データ メンバーは、プログラムの実行開始時に存在する必要があります。関数はプログラムの実行中に呼び出されるため、関数内で静的データ メンバーを割り当てたり初期化したりすることはできません。

このように、スペース割り当てには 3 つの場所が考えられます。1 つはクラスの外部インターフェイスとしてのヘッダー ファイルで、2 つはクラス定義の内部実装です。クラスのメンバー関数定義、3 番目は main() 関数の前のアプリケーションのグローバル データ宣言と定義です。

静的データ メンバーは実際に領域を割り当てる必要があるため、クラスの宣言で定義できません (宣言できるのはデータ メンバーのみです)。クラス宣言はクラスの「サイズと仕様」を宣言するだけで、実際のメモリ確保は行いませんので、クラス宣言に定義を書くのは間違いです。また、ヘッダー ファイルのクラス宣言の外で定義することもできません。その場合、そのクラスを使用する複数のソース ファイルで再定義されることになります。引 Static は、スタック上の領域ではなくプログラムの静的記憶領域に変数が初期化されたことをコンパイラに通知するために導入されました。削除の順序は初期化の逆の順序です。

5. 静的の利点:
すべてのオブジェクトに共通であるため、メモリを節約できます。したがって、複数のオブジェクトの場合、静的データ メンバーはすべてのオブジェクトで共有される 1 つの場所にのみ保存されます。静的データ メンバーの値はすべてのオブジェクトで同じですが、その値は更新できます。静的データ メンバーの値が一度更新される限り、すべてのオブジェクトは同じ更新された値にアクセスすることが保証されるため、時間効率が向上します。

6. 静的データ メンバーを参照する場合は、次の形式を使用します。

、静的データ メンバーは、上記の形式に従ってプログラム内で参照できます。

7. 注意事項:
(1)クラスの静的メンバー関数は、クラスのオブジェクトではなくクラス全体に属しますので、このポインターを持たず、その結果、静的メンバー関数のみにアクセスしますクラスメンバー関数のデータと静的データ。
(2) 静的メンバー関数は仮想関数として定義できません。
(3) 静的メンバーはクラス内で宣言され、その外部で動作するため、そのアドレスを取得する操作は若干特殊です。変数 address はそのデータ型 へのポインターであり、関数のアドレス型は「非メンバー」です。関数ポインター”。

(4) 静的メンバー関数にはこのポインターがないため、非メンバー関数とほぼ同等になります。その結果、予想外の利点が得られます。これにより、C++ と C を組み合わせることができます。ベースの X Window システムであると同時に、スレッド関数への適用にも成功しました。
(5) static は、プログラムの時間とスペースのオーバーヘッドを増加させません。それどころか、親クラスの静的メンバーへのサブクラスのアクセス時間も短縮され、サブクラスのメモリスペースが節約されます。 ️ (6) する場合、静的データ メンバーの前にキーワード static が付けられます。
(7)
静的データメンバーは静的に格納されるため、初期化する必要があります。 (8) 静的メンバーの初期化は、一般的なデータ メンバーの初期化とは異なります:
use using using using out out through out クラス本体の ‐ ‐ ‐ ‐‐‐‐‐
制御記号 Private、Public など。 スコープ演算子
のスコープを使用して、初期化時に所属するクラスを指定します。 =
(9) 親クラスの影響を防ぐために、次のように定義できます。親クラスの影響をシールドするために、親クラスと同じサブクラス内の静的変数。ここで注意すべき点が 1 つあります。静的メンバーは親クラスとサブクラスで共有されると言っていますが、静的メンバーを繰り返し定義するとエラーが発生しますか?いいえ、私たちのコンパイラは、名前のマングリングという気の利いたトリックを使用して一意の識別子を生成します。

静的データメンバー

クラスにおいて、静的メンバーは複数のオブジェクト間でのデータ共有を実現することができ、静的データメンバーを使用することで隠蔽の原理を崩さない、つまり安全性が保証されます。したがって、静的メンバーは、特定のオブジェクトのメンバーではなく、クラスのすべてのオブジェクト間で共有されるメンバーです。

静的データ メンバーを使用すると、すべてのオブジェクトに共通であるため、メモリを節約できます。したがって、複数のオブジェクトの場合、静的データ メンバーはすべてのオブジェクトで共有される 1 つの場所にのみ保存されます。静的データ メンバーの値はすべてのオブジェクトで同じですが、その値は更新できます。静的データ メンバーの値が一度更新される限り、すべてのオブジェクトは同じ更新された値にアクセスすることが保証されるため、時間効率が向上します。

静的データメンバーの使用方法と注意事項は以下のとおりです。

1. 静的データメンバーの定義または説明の前にキーワード static を追加します。

2. 静的メンバーの初期化は、一般的なデータメンバーの初期化とは異なります。静的データメンバの初期化形式は以下の通りです:

<データ型><クラス名>::<静的データメンバ名>=<値>

これは以下を示します:

(1)での初期化一般的な静的変数やオブジェクトとの混同を避けるために、前に static を追加せずにクラスの外側で実行されます。

(2) 初期化中にメンバーのアクセス制御文字 private、public などを追加しないでください。

(3) 初期化中にスコープ演算子を使用して、それが属するクラスを示します。 したがって、静的データメンバーはオブジェクトではなくクラスのメンバーです。

3. 静的データメンバーは静的に保存されるため、初期化する必要があります。

4. 静的データメンバーを参照する場合は、次の形式を使用します:

<クラス名>::<静的メンバー名>

静的データメンバーのアクセス権が許可している場合(つまり、パブリックメンバー)を使用すると、プログラム内で上記の形式に従って静的データ メンバーを参照できます。

静的メンバー関数

静的メンバー関数は静的データメンバーと同じです。どちらもクラスの静的メンバーであり、オブジェクトのメンバーではありません。したがって、静的メンバーへの参照ではオブジェクト名を使用する必要はありません。

静的メンバー関数の実装では、クラスに記述された非静的メンバーを直接参照することはできませんが、クラスに記述された静的メンバーは参照できます。静的メンバー関数で非静的メンバーを参照する必要がある場合は、オブジェクトを通じて参照できます。


例を見てみましょう:

#
include
 <iostream.h>
class Point
{
public:
void output()
{
}
static void init()
{  
} 
};
void main( void )
{
Point pt;
pt.init();
pt.output(); 
}
ログイン後にコピー

このようにコンパイルするとエラーは発生しません。
こんな感じ

#include <iostream.h>
class Point
{
public:
void output()
{  
}
static void init()
{  
} 
};
void main( void )
{
Point::output();
}
ログイン後にコピー

このようにコンパイルすると、エラーメッセージ:illegalcallofnon-staticmemberが発生します。 機能 、なぜですか? クラスの特定のオブジェクトがインスタンス化されていない場合、クラスにはメモリ空間が割り当てられないためです。
さて、次の例を見てください:

#include <iostream.h>
class Point
{
public:
void output()
{  
}
static void init()
{  
} 
};
void main( void )
{
Point::init();
}
ログイン後にコピー

クラスが定義されるとき、その静的データとメンバー関数は独自のメモリ領域を持ち、どのメモリ領域にも属さないため、現時点ではコンパイルでエラーは発生しません。特定のオブジェクトの一部。

次の例を見てください:

#include <iostream.h>
class Point
{
public:
void output()
{  
}
static void init()
{ 
   x = 0;
   y = 0;
}
private:
int x;
int y;
};
void main( void )
{
Point::init();
}
ログイン後にコピー

コンパイル エラー:


illegal 静的 member のデータ member 'Point::x' function
illegal 静的メンバー
メンバー関数内のデータメンバー「Point::y」への参照静的メンバー関数では、データメンバーが誤って参照されています
問題は依然として同じであり、静的メンバーです。 (関数 ) が特定のオブジェクトに属していない場合、クラスの特定のオブジェクトが宣言される前にすでにメモリ領域が存在し、非静的データ メンバーにメモリ領域が割り当てられていない場合、ここでの呼び出しは間違っています。宣言されていない場合と同じです。変数を事前に使用する場合と同じです。
つまり、静的メンバー関数では非静的メンバー変数を参照できません。
それでは、以下の例を見てみましょう:

#include <iostream.h>class Point{public:void output(){   x = 0;   y = 0;   init();  }static void init(){
}private:int x;int y;};void main( void ){Point::init();}
ログイン後にコピー

好的,这样就不会有任何错误。这最终还是一个内存模型的问题,
任何变量在内存中有了自己的空间后,在其他地方才能被调用,否则就会出错。
好的再看看下面的例子:

#include <iostream.h>
class Point
{
public:
void output()
{ 
}
static void init()
{ 
   x = 0;
   y = 0;
}
private:
static int x;
static int y;
};
void main( void )
{
Point::init();
}
ログイン後にコピー

编译:
Linking...
test.obj : error LNK2001: unresolved external symbol "private: static int Point::y"
test.obj : error LNK2001: unresolved external symbol "private: static int Point::x"
Debug/Test.exe : fatal error LNK1120: 2 unresolved externals
执行 link.exe 时出错.
可以看到编译没有错误,连接错误,这又是为什么呢?
这是因为静态的成员变量要进行初始化,可以这样:

#include <iostream.h>
class Point
{
public:
void output()
{ 
}
static void init()
{ 
   x = 0;
   y = 0;
}
private:
static int x;
static int y;
};
int Point::x = 0;
int Point::y = 0;
void main( void )
{
Point::init();
}
ログイン後にコピー

在静态成员数据变量初始化之后就不会出现编译错误了。
再看看下面的代码:

#include <iostream.h>
class Point
{
public:
void output()
{ 
}
static void init()
{ 
   x = 0;
   y = 0;
}
private:
static int x;
static int y;
};
void main( void )
{
}
ログイン後にコピー

编译没有错误,为什么?
即使他们没有初始化,因为我们没有访问x,y,所以编译不会出错。

C++会区分两种类型的成员函数:静态成员函数和非静态成员函数。这两者之间的一个重大区别是,静态成员函数不接受隐含的this自变量。所以,它就无法访问自己类的非静态成员。

在某些条件下,比如说在使用诸如pthread(它不支持类)此类的多线程库时,就必须使用静态的成员函数,因为其地址同C语言函数的地址兼容。这种铜限制就迫使程序员要利用各种解决办法才能够从静态成员函数访问到非静态数据成员。

第一个解决办法是声明类的所有数据成员都是静态的。运用这种方式的话,静态的成员函数就能够直接地访问它们,例如:

class Singleton
{
public:
   static Singleton * instance();
private:
   Singleton * p;
   static Lock lock;
};
Singleton * Singleton::instance()
{
lock.getlock(); 
// fine, lock is static
if (!p)
   p=new Singleton;
lock.unlock();
return p;
}
ログイン後にコピー


这种解决方法不适用于需要使用非静态数据成员的类。

访问非静态数据成员

将参照传递给需要考量的对象能够让静态的成员函数访问到对象的非静态数据:

class A
{
public:
   static void func(A & obj);
   intgetval() const; 
//
non-static
 
member
 
function
private:
intval;
};
ログイン後にコピー


静态成员函数func()会使用参照obj来访问非静态成员val

voidA::func(A & obj)
{
   int n = obj.getval();
}
ログイン後にコピー


将一个参照或者指针作为静态成员函数的自变量传递,就是在模仿自动传递非静态成员函数里this自变量这一行为。

以上がPHPにおける静的キーワードの役割の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート