正文 第七章 類的其它特性(3 / 3)

如有可能,就應該將成員函數說明為const類型,以便允許聲明的常量對象使用自己的類。

應該注意:成員函數的返回類型是const與const成員函數兩者的區別。

7.3友員

在開始學習類的時候我們介紹過:最好將類的數據成員聲明為私有的,以使類之外的函數不能訪問它們。但是,有時我們會發現兩個或多個類之間存在著很密切的關係,並希望一個類能直接訪問另一類的私有數據。而在C++中,隻要是非類的成員,便不得使用該類所有的私有成員。如果將此數據定義成公有的,再互相使用一個訪問函數顯然是很不經濟的。在ViSValC++中,允許通過關鍵字friend來擴大私有成員的訪問權限。這樣,就引出了友員的概念。類的友員包括友員函數和友函類兩種。

一、友員函數

可以用friend關鍵字來聲明一個友員函數,它說明的一般形式為:

如果把一個函數聲明為友員函數,就可以在該友員函數中訪問類的對象和私有數據了。

例中的說明語句:friendvoidFriendSet(Myclass&ob,intv);

說明函數FriendSet()是類Myclass的友員,它可以訪問類Myclass對象的私有數據成員,如:ob.value=v;

友員函數並不是類的成員函數,它其實就是一個普通的函數,隻不過在類中被聲明為該類的友員函數後,它就可以訪問該類對象的私有數據成員。

關於友員函數,有如下說明:

1.友員函數必須在類的說明體中明。既可以在私有部分說明,也可以在公有部分說明。

2.友員函數不是類的成員函數,因此,它不能直接訪問類的成員,而隻能訪問類的對象的成員。

3.如果在說明友員函數時,給出了該函數的函數體代碼,則該友員函數是內聯的。

4.類的成員函數也可以用作其它類的友員。

5.對於類的成員函數,當它被調用時,編譯器會把this指針作為隱含的參數傳遞給它。this指向當前調用該函數的對象上。因此,在成員函數中,被直接訪問的類成員指的是當前對象的成員。而對於類的友員函數,當它被調用時,編譯器並沒有將thb指針傳遞給它。所以,它並不知道當前的對象是誰,因而,它就不能直接訪問類的成員,而隻能訪問具體對象的成員。

6.使用友員函數的主要目的是為了提髙程序的效率。友員函數由於可以直接訪問對象的私有成員,因而省去了調用類的成員函數的開銷。它的另一個優點是:在設計一個類之前,不必考慮好該類的各種使用情況,而可以在完成類的設計後,根據需要,通過友員的使用增加類的接口。但是,使用友員也存在一個問題就是:允許友員函數訪問對象的私有成員,這將破壞類的封裝性和數據的隱藏,從而降低程序的可維護性。因此,在使用友員時,必須權衡得失,盡量少地使用友員函數。

友員不僅僅局限於函數,整個類也可以是另一個類的友員。定義一個類為友員,相當於把這個類的所有成員函數定義為友員。在聲明友員類時,friend的聲明位置不受任何限製。

在下麵的例子中,類A將類B聲明為一個友員。這就允許類B的成員函數直接讀取或修改類汸的私有成員。

在這個例子中,類B在類A中被通過語句friendclassB;聲明為A的友員,這就意味著類B的所有成員函數(包括構造函數和析構函數)將成為類A的友員函教,所以在類B的Set()函數中。

在聲明一個類時,可以指定某些其它的類為你的類的友員類r但是,卻不能在定義其它的類時,再指明那個類為你的類的友員類。這樣,我們就能控製哪些人能夠訪問自己編寫的類了。

要注意,friend關鍵字提供了單向的訪問權限。當類A是類B的友員肘,類B不一定是類A的友員,除非你將類B再說明為類A的友員。同樣,友員關係也沒有傳遞性,即如果類A是類B的友員,而類B又是類C的友員,那麼,類A不一定是類C的友員。

7.4舉例

例7.8類Lock用來控製對一個公共資源的訪問權。靜態數據成員status用來記錄公共資源的狀態:當status為0時,表示該資源已被占用;當status為1時,表示該資源處於空閑狀態,可供使用。

練習:

1.舉例說明靜態成員與非靜態成員的區別。

2.如何去初始化const數據成員?

3.成員初始化表的作用是什麼?

4.為什麼要使用類的友員?

5.友員與靜態成員函數的相似和不同之處是什麼?