1. 程式人生 > >c++ primer 學習筆記23 友元 static類成員

c++ primer 學習筆記23 友元 static類成員

友元機制允許一個類將對其非公有成員的訪問權授予指定的函式或類。友元的宣告以關鍵字 friend 開始。它只能出現在類定義的內部。友元宣告可以出現在類中的任何地方:友元不是授予友元關係的那個類的成員,所以它們不受宣告出現部分的訪問控制影響。
通常,將友元宣告成組地放在類定義的開始或結尾是個好主意。
友元可以是普通的非成員函式,或前面定義的其他類的成員函式,或整個類。將一個類設為友元,友元類的所有成員函式都可以訪問授予友元關係的那個類的非公有成員。
使其他類的成員函式成為友元
如果不是將整個 Window_Mgr 類設為友元,Screen 就可以指定只允許relocate 成員訪問:

 class Screen { 
         // Window_Mgrmust be defined before class Screen 
         friend Window_Mgr& 
             Window_Mgr::relocate(Window_Mgr::index, 
                                  Window_Mgr::index,
                                   Screen&); 
         // ...restofthe Screen class
};

當我們將成員函式宣告為友元時,函式名必須用該函式所屬的類名字加以限定。
更一般地講,必須先定義包含成員函式的類,才能將成員函式設為友元。另一方面,不必預先宣告類和非成員函式來將它們設為友元。

static 類成員

通常,非 static 資料成員存在於類型別的每個物件中。不像普通的資料成員,static 資料成員獨立於該類的任意物件而存在;每個 static 資料成員是與類關聯的物件,並不與該類的物件相關聯。
正如類可以定義共享的 static 資料成員一樣,類也可以定義 static 成員函式。static 成員函式沒有 this 形參,它可以直接訪問所屬類的 static 成員,但不能直接使用非 static 成員。
使用類的 static 成員的優點


使用 static 成員而不是全域性物件有三個優點。
1. static 成員的名字是在類的作用域中,因此可以避免與其他類的成員或全域性物件名字衝突。
2. 可以實施封裝。static 成員可以是私有成員,而全域性物件不可以。
3. static 成員是與特定類關聯的。這種可見性可清晰地顯示程式設計師的意圖。

 class Account { 
     public: 
         // interface functions here 
         void applyint() { amount += amount * interestRate; } 
         static double rate() { return interestRate; } 
         static void rate(double); // sets a new rate 
     private: 
         std::string owner; 
         double amount; 
         static double interestRate; 
         static double initRate(); 
     }; 

使用類的 static 成員
可以通過作用域操作符從類直接呼叫 static 成員,或者通過物件、引用或指向該類型別物件的指標間接呼叫。

     Account ac1; 
     Account *ac2 = &ac1; 
     // equivalent ways to call the static member rate function 
     double rate; 
     rate = ac1.rate();        // through an Account object or reference 
     rate = ac2->rate();       // through a pointer to an Account object 
     rate = Account::rate();   // directly from the class using the scope 
operator 

static 成員函式
Account 類有兩個名為 rate 的 static 成員函式,其中一個定義在類的內部。當我們在類的外部定義 static 成員時,無須重複指定 static 保留字,該保留字只出現在類定義體內部的宣告處:

 void Account::rate(double newRate) 
     { 
         interestRate = newRate; 
     } 

static 函式沒有 this 指標
static 成員是類的組成部分但不是任何物件的組成部分,因此,static 成員函式沒有 this 指標。
因為 static 成員不是任何物件的組成部分,所以 static 成員函式不能被宣告為 const。畢竟,將成員函式宣告為 const 就是承諾不會修改該函式所屬的物件。最後,static 成員函式也不能被宣告為虛擬函式。
static 資料成員
static 資料成員必須在類定義體的外部定義(正好一次)。不像普通資料成員,static 成員不是通過類建構函式進行初始化,而是應該在定義時進行初始化。
可以定義如下 interestRate:

  // define and initialize static class member 
     double Account::interestRate = initRate(); 

像使用任意的類成員一樣,在類定義體外部引用類的 static 成員時,必須指定成員是在哪個類中定義的。然而,static 關鍵字只能用於類定義體內部的宣告中,定義不能標示為 static。
特殊的整型 const static 成員
一般而言,類的 static 成員,像普通資料成員一樣,不能在類的定義體中初始化。相反,static 資料成員通常在定義時才初始化。
這個規則的一個例外是,只要初始化式是一個常量表達式,整型 const static 資料成員就可以在類的定義體中進行初始化:

 class Account { 
     public: 
         static double rate() { return interestRate; } 
         static void rate(double);  // sets a new rate 
     private: 
         static const int period = 30; // interest posted every 30 days 
         double daily_tbl[period]; // ok: period is constant expression 
     }; 

const static 資料成員在類的定義體中初始化時,該資料成員仍必須在類的定義體之外進行定義。

在類內部提供初始化式時,成員的定義不必再指定初始值: 
     // definition of static member with no initializer; 
     // the initial value is specified inside the class definition 
     const int Account::period;