搜尋
首頁後端開發php教程php中static關鍵字的作用

php中static關鍵字的作用

Jul 02, 2017 am 11:54 AM
phpstatic關鍵字

對下面文章的總結:

1.對於靜態變數而言:在地化(名字衝突)、初始化=0、唯一共享性(靜態區) 。特別地,對於類別靜態成員變數:(1)屬於整個類,可以直接透過類別名稱存取而不用透過實例(2)必須初始化,類別內st​​atic聲明,類別外初始化(不可以再加static)

2.對於類別靜態成員函數而言,(1)沒有this指針,僅能存取靜態成員變數和靜態成員函數,不能宣告為虛函數(2)常用於多執行緒中的子類別。

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

1、什麼是static?
       static 是C++中很常用的修飾符,它被用來控制變數的儲存方式和可見性。

    2.為什麼要引入static?
       函數內部定義的變數,當程式執行到它的定義處時,編譯器為它在堆疊上分配空間,大家知道,函數在堆疊上分配的空間在此函數執行結束時會釋放掉,這樣就產生了一個問題: 如果想將函數中此變數的值保存至下一次呼叫時,如何實現? 最容易想到的方法是定義一個全域的變量,但定義為一個全域變數有許多缺點,最明顯的缺點是破壞了此變數的存取範圍(使得在此函數中定義的變量,不僅僅受此函數控制)。

    3、何時用static?
       需要一個資料物件為整個類別而非某個物件服務,同時又力求不破壞類別的封裝性,即要求此成員隱藏在類別中的內部,對外不可見。

    4、static的內部機制:
       靜態資料成員在程式一開始運作時必須存在。因為函數在程式運行中被調用,所以靜態資料成員不能在任何函數內分配空間和初始化。
       這樣,它的空間分配有三個可能的地方,一是作為類的外部接口的頭文件,那裡有類聲明;二是類定義的內部實現,那裡有類的成員函數定義;三是應用程式的main()函數前的全域資料宣告與定義處。
      靜態資料成員要實際分配空間,因此不能定義在類別的宣告中(只能宣告資料成員)。類別聲明只聲明一個類別的“尺寸和規格”,並沒有進行實際的記憶體分配,所以在類別聲明中寫成定義是錯誤的。它也不能在頭檔中類別聲明的外部定義,因為那會造成在多個使用該類別的來源檔案中,對其重複定義。
      static被引入以告知編譯器,將變數儲存在程式的靜態儲存區而非堆疊上空間,靜態
資料成員依定義出現的先後順序依序初始化,注意靜態成員巢狀時,要保證所嵌套的成員已經初始化了。消除時的順序是初始化的反順序。

    5、static的優點:
       可節省內存,因為它是所有物件所公有的,因此,對於多個物件來說,靜態資料成員只儲存一處,供所有物件共用。靜態資料成員的值對每個物件都是一樣,但它的值是可以更新的。只要對靜態資料成員的值更新一次,確保所有物件存取更新後的相同的值,這樣可以提高時間效率。

    6、引用靜態資料成員時,採用下列格式:
         #類別名稱>::靜態成員名稱>

###############1## #    如果靜態資料成員的存取權限允許的話(即public的成員),可在程式中,按上述格式來引用靜態資料成員。 ###

    7、注意事項
      (1)類別的靜態成員函數是屬於整個類別而非類別的物件,所以它沒有this指針,這就導致了它僅能存取類別的靜態資料和靜態成員函數。
      (2)無法定義靜態成員函數為虛函數。
      (3)由於靜態成員宣告於類別中,操作於其外,所以對其取位址操作,就多少有些特殊,變數位址是指向其資料類型的指針,函數位址類型是一個「nonmember函數指標」。

      (4)由於靜態成員函數沒有this指針,所以就差不多等同於nonmember函數,結果就產生了一個意想不到的好處:成為一個callback函數,使得我們得以將C++和C-based X Window系統結合,同時也成功的應用於執行緒函數身上。
      (5)static並沒有增加程式的時空開銷,相反她也縮短了子類別對父類別靜態成員的存取時間,節省了子類別的記憶體空間。
      (6)靜態資料成員在時前面加關鍵字static。
      (7)靜態資料成員是靜態儲存的,所以必須對它進行初始化。
      (8)靜態成員初始化與一般資料成員初始化不同:
       初始化在類體外進行,而前面不加static
#,以免與一般靜態變數或物件混淆;
       初始化時不加該成員的存取權控制符private,public等;           初始化時使用作用域 所以成員初始化的格式:
         ::=
      (9)為了防止父類別的影響,可以在子類別中定義一個與父類別相同的靜態變量,以屏蔽父類別的影響。這裡有一點要注意:我們說靜態成員為父類別和子類別共享,但我們有重複定義了靜態成員,這會不會造成錯誤呢?不會,我們的編譯器採用了絕妙的手法:name-mangling 用來產生唯一的標誌。

靜態資料成員

  在類別中,靜態成員可以實現多個物件之間的資料共享,並且使用靜態資料成員還不會破壞隱藏的原則,即保證了安全性。因此,靜態成員是類別的所有物件中共享的成員,而不是某個物件的成員。

  使用靜態資料成員可以節省內存,因為它是所有物件所公有的,因此,對多個物件來說,靜態資料成員只儲存一處,供所有物件共用。靜態資料成員的值對每個物件都是一樣,但它的值是可以更新的。只要對靜態資料成員的值更新一次,確保所有物件存取更新後的相同的值,這樣可以提高時間效率。

  靜態資料成員的使用方法與注意事項如下:

  1、靜態資料成員在定義或說明時前面加關鍵字static。

  2、靜態成員初始化與一般資料成員初始化不同。靜態資料成員初始化的格式如下:

    ::=

#  這表示:

        (1) 初始化在類別體外進行,而前面不加static,以免與一般靜態變數或物件混淆。

  (2) 初始化時不加該成員的存取權限控制符private,public等。

  (3) 初始化時使用作用域運算子來標示它所屬類,因此,靜態資料成員是類別的成員,而不是物件的成員。

  3、靜態資料成員是靜態儲存的,它是靜態生存期,必須對它進行初始化。

  4、引用靜態資料成員時,採用以下格式:

   ::

  如果靜態資料成員的存取權限允許的話(即public的成員),可在程式中,按上述格式來引用靜態資料成員。

靜態成員函數

  靜態成員函數和靜態資料成員一樣,它們都屬於類別的靜態成員,它們都不是物件成員。因此,對靜態成員的引用不需要用物件名稱。

  在靜態成員函數的實作中不能直接引用類別中所說明的非靜態成員,可以引用類別中所說明的靜態成員。如果靜態成員函數中要引用非靜態成員時,可透過物件來引用。


下面看一個例子:

#
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();
}

這樣編譯會處錯,錯誤訊息illegal##  call of #non-static memberfunction,為什麼? 因為在沒有實例化一個類別的具體物件時,類別是沒有被分配記憶體空間的。
好的再看看下面的例子:

#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 reference to data ## member 'Point::x' in a static member function
illegal
# reference to data member 'Point::y' in a static member function
##在一個靜態成員函數裡錯誤的引用了資料成員,
還是那個問題,靜態成員(函數),不屬於任何一個具體的對象,那麼在類別的具體對象宣告之前就已經有了記憶體區,
而現在非靜態資料成員還沒有分配記憶體空間,那麼這裡呼叫就錯誤了,就好像沒有聲明一個變數卻提前使用它一樣。
也就是說在靜態成員函數中不能引用非靜態的成員變數。
好的再看看下面的例子:

#
#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中static關鍵字的作用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
繼續使用PHP:耐力的原因繼續使用PHP:耐力的原因Apr 19, 2025 am 12:23 AM

PHP仍然流行的原因是其易用性、靈活性和強大的生態系統。 1)易用性和簡單語法使其成為初學者的首選。 2)與web開發緊密結合,處理HTTP請求和數據庫交互出色。 3)龐大的生態系統提供了豐富的工具和庫。 4)活躍的社區和開源性質使其適應新需求和技術趨勢。

PHP和Python:探索他們的相似性和差異PHP和Python:探索他們的相似性和差異Apr 19, 2025 am 12:21 AM

PHP和Python都是高層次的編程語言,廣泛應用於Web開發、數據處理和自動化任務。 1.PHP常用於構建動態網站和內容管理系統,而Python常用於構建Web框架和數據科學。 2.PHP使用echo輸出內容,Python使用print。 3.兩者都支持面向對象編程,但語法和關鍵字不同。 4.PHP支持弱類型轉換,Python則更嚴格。 5.PHP性能優化包括使用OPcache和異步編程,Python則使用cProfile和異步編程。

PHP和Python:解釋了不同的範例PHP和Python:解釋了不同的範例Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP和Python:深入了解他們的歷史PHP和Python:深入了解他們的歷史Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

在PHP和Python之間進行選擇:指南在PHP和Python之間進行選擇:指南Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

PHP和框架:現代化語言PHP和框架:現代化語言Apr 18, 2025 am 12:14 AM

PHP在現代化進程中仍然重要,因為它支持大量網站和應用,並通過框架適應開發需求。 1.PHP7提升了性能並引入了新功能。 2.現代框架如Laravel、Symfony和CodeIgniter簡化開發,提高代碼質量。 3.性能優化和最佳實踐進一步提升應用效率。

PHP的影響:網絡開發及以後PHP的影響:網絡開發及以後Apr 18, 2025 am 12:10 AM

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型?PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型?Apr 17, 2025 am 12:25 AM

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境