類內靜態函式和全域性靜態函式的相同點和不同點

2021-06-03 23:42:45 字數 2872 閱讀 9221

1)全域性靜態函式只在本編譯單元有效。

2)類靜態函式,對比普通成員函式,沒有this指標,不能訪問非static成員。

3)要說二者相同點,都是c++名字控制的手段:全域性靜態函式被侷限在乙個編譯單元,通俗的將就是在乙個cpp檔案中定義的全域性靜態函式在另乙個cpp檔案中不能被呼叫。例程如下;

#includeusing namespace std;

class a

當我們希望在多個類中呼叫fun函式時,我們必須把fun宣告為static型別,不然在link時編譯器會發現多個關於fun的定義。這種函式的應用,多少帶有c的色彩,尤其當我們在c環境寫好的函式,移植到c++中時,需要在函式前面需要加上static,而如果我們需要移植多個函式時,更通用的一種方法是使用未命名名字空間

namespace

… }

也許有人問如果在未命名名字空間中的函式再加上static修飾符號會怎麼樣?這個就完全取決以使用的編譯器,可能會直接報錯,也可能可以編譯並正常使用。不過這樣寫,**從語言層次上就很難移植編譯環境,所以盡量不要這樣寫。

關於這樣的應用,在我從前的專案中實施過。當時我需要定義很多函式,執行三角形,已經畫素轉換方面的計算,所以把這些函式宣告為static的。

對於與全域性靜態函式,我們繼續類內靜態函式和靜態變數的討論,我想他們的應用是兩者區別的最好體現。

對於類內靜態變數,我們需要在類外初始化,這是在使用靜態變數需要注意的地方,有些初學者很容易在這裡出錯。類內靜態變數使用最多的就是計算類的例項化個數。

class   a

~a()   //   析構函式  

static   int   createobjectnumber()   //   或者建立物件的數目

}; 也許讀者認為這種方法,只是用來學習而已,實際很少使用。我不贊同這個觀點。

1:靜態變數受public,protected   ,private限制,也就是如果靜態變數是protected或者private型別的,在類外不能訪問,比如

a::i是錯誤的

這條規則同樣適用於靜態函式

2:靜態變數在類內宣告,而必須在類外初始化,模版類中應用也是這樣。這裡我們在static後面加上const型別,可以直接初始化。比如

class   a

而這裡i的應用也無非是int   m_list[i];

3:靜態成員函式只能訪問類的靜態變數,而類的成員函式也可以訪問類的靜態變數,這樣就可以通過靜態成員變數建立類的靜態成員函式和類物件的關聯關係。

4:還存在一種靜態變數,他不是全域性靜態變數,而是函式內的靜態變數,如下例中的i,這算是對全域性靜態變數的一種補充。

int   fun()

這種方式的好處時,只用呼叫fun函式時,靜態變數i才申請記憶體,這也符合lazy   evaluation的設計要求。只有當需要時,才去申請。

同樣作為破壞封裝的一種技術應用是友元函式或者友元類的應用,很多人形象比喻這種方式是在封裝的物體上開了乙個小小的洞,不提倡使用這種技術。其實任何技術都有他應用的場所,不然就不會出現這種技術。不過不去了解這種特性,也許永遠我們不會知道這些技術的重要性。碰見這些技術也只會使用有色眼鏡去看。友元函式的特徵基本如下

1) 必須在類的說明中說明友元函式,說明時以關鍵字friend開頭,後跟友元函式的函式原型,友元函式的說明可以出現在類的任何地方,包括在private和public部分,不受private限制  

2) 友元函式不是類的成員函式,所以友元函式的實現和普通函式一樣,在實現時不用 ":: "指示屬於哪個類,只有成員函式才使用 ":: "作用域符號;

3) 友元函式不能直接訪問類的成員,只能訪問物件成員,所以在調用友元函式時,確保友元類的必須例項化。

4) 友元函式可以訪問物件的私有成員,但普通函式不行,這個需要注意,尤其是在友元類中,有時候發現兩個類互相為友元類,確不能呼叫成員函式,就是這個原因。

5) 調用友元函式時,在實際引數中需要指出要訪問的物件,也可以把物件宣告為全域性物件而在友元函式中呼叫,當然在友元函式中可以呼叫其他全域性函式,或者例項物件等操作。

使用友員函式最大的優點就是,不用對類中的每個變數寫get/set介面函式。尤其是當類中有大量的私有成員變數,而又不想為每個變數設定介面,同時又需要外部的某個函式呼叫。這樣最好就是把這個函式宣告為友元函式,我們在一些開源專案中很常見這種技術,比如阿agentx++。

class   au

; string   getau()

virtual   string   getauu()

; virtual   ~au(){};

}; template  

class   temu:public   tbase

string   getbb()

public:

string   geta()

string   getb()

}; class   derivetemu   :   public   temu

string   getb()

}; 測試用力

derivetemu   u;

temu *p   =   &u;

cout   < <   p-> getaa()   < <   endl;

cout   < <   p-> getbb()   < <   endl;

輸出結果  

derivetemu   -   geta

derivetemu   –   getb

在這裡我們看到,呼叫類內靜態函式的方式並不是簡單的類名::函式的形式,而是通過模版父類呼叫子類靜態函式,同樣也給出了,呼叫普通函式的方式。這種機制可以理解為模版繼承關係中的虛繼承關係。當認識到模版中的靜態函式使用,也許會更大的改變我們對靜態函式的印象,這種機制在atl,wtl中有廣泛的應用,幾乎每種涉及到訊息影射關係的類中,都使用這種方式。

時間類 靜態函式

corpyright c 2013,煙台大學計算機學院 all right reseved.完成日期 2014年4月1日 版本號 v1.0 輸入描述 問題描述 時間類!程式輸出 問題分析 演算法設計 include using namespace std class time void show t...

靜態函式與非靜態函式的區別

靜態成員函式和非靜態成員函式的根本區別在於有無this指標。非靜態函式由物件名或者物件指標 呼叫,呼叫時編譯器會向函式傳遞this指標 靜態成員函式則由類名 或者物件名呼叫 非靜態函式中有this指標,靜態函式中沒有this指標,不能訪問物件的成員函式,成員函式有this指標,const修飾this...

繼承 類函式 靜態函式

coding utf 8 類的繼承 1.子類繼承自父類,子類擁有父類的所有屬性和函式 2.子類繼承自父類,子類可以擁有自己獨有的屬性和函式,父類不可以使用子類獨有的屬性和函式 3.子類繼承自父類,子類可以重寫父類的函式 3.1 完全重寫,在子類中重新定義乙個和父類函式名稱一樣的函式,但是這個函式執行...