static類成員(變量和函數)

0. 使用背景面試

對於特定類類型的全體對象而言,訪問一個全局對象有時是必要的。
也許,在程序的任意點須要統計已建立的特定類類型對象的數量;
或者,全局對象多是指向類的錯誤處理例程的一個指針;
或者,它是指向類類型對象的內在自由存儲區的一個指針。
然而,全局對象會破壞封裝:對象須要支持特定類抽象的實現。
若是對象是全局的,通常的用戶代碼就能夠修改這個值。express

1. static 類成員數組

類能夠定義類 靜態成員,而不是定義一個可廣泛訪問的全局對象。
一般,非 static 數據成員存在於類類型的每一個對象中。
不像普通的數據成員,static 數據成員獨立於該類的任意對象而存在;
每一個 static 數據成員是與類關聯的對象,並不與該類的對象相關聯。
正如類能夠定義共享的 static 數據成員同樣,類也能夠定義 static 成員函數。
static 成員函數沒有 this 形參,它能夠直接訪問所屬類的 static 成員,但不能直接使用非 static 成員。app

1.1 使用類的 static 成員的優勢ide

使用 static 成員而不是全局對象有 3 個優勢:
  static 成員的名字是在類的做用域中,所以能夠避免與其餘類的成員或全局對象名字衝突。
  能夠實施封裝。static 成員能夠是私有成員,而全局對象不能夠。
  經過閱讀程序容易看出 static 成員是與特定類關。函數

1.2 定義 static 成員post

在成員聲明前加上關鍵字 static 將成員設爲 static。static 成員遵循正常的公有/私有訪問規則。
例如,考慮一個簡單的表示銀行帳戶的類。
每一個帳戶具備餘額和擁有者,而且按月得到利息,但應用於每一個帳戶的利率老是相同的。ui

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

這個類的每一個對象具備兩個數據成員:owner 和 amount。
對象沒有與 static 數據成員對應的數據成員,
可是,存在一個單獨的 interestRate 對象,由 Account 類型的全體對象共享。this

1.3 使用類的 static 成員spa

能夠經過做用域操做符從類直接調用 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 成員:

class Account {
public:
  // interface functions here
  void applyint() { amount += amount * interestRate; }
};

2. static 成員函數

Account 類有兩個名爲 rate 的 static 成員函數,其中一個定義在類的內部。
當咱們在類的外部定義 static 成員時,無須重複指定 static 保留字,該保留字只出如今類定義體內部的聲明處:

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

static 成員是類的組成部分但不是任何對象的組成部分,所以,static 成員函數沒有 this 指針。
經過使用非 static 成員顯式或隱式地引用 this 是一個編譯時錯誤。
由於 static 成員不是任何對象的組成部分,因此 static 成員函數不能被聲明爲 const。
畢竟,將成員函數聲明爲 const 就是承諾不會修改該函數所屬的對象。
最後,static 成員函數也不能被聲明爲虛函數。

3. static 數據成員

static 數據成員能夠聲明爲任意類型,能夠是常量、引用、數組、類類型,等等。
static 數據成員必須在類定義體的外部定義(正好一次)
不像普通數據成員,static 成員不是經過類構造函數進行初始化,而是應該在定義時進行初始化。
保證對象正好定義一次的最好辦法,就是將 static 數據成員的定義放在包含類非內聯成員函數定義的文件中。

定義 static 數據成員的方式與定義其餘類成員和變量的方式相同:先指定類型名,接着是成員的徹底限定名。
能夠定義以下 interestRate:

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

這個語句定義名爲 interestRate 的 static 對象,它是類 Account 的成員,爲 double 型。
像其餘成員定義同樣,一旦成員名出現,static 成員的就是在類做用域中。
所以,咱們能夠沒有限定地直接使用名爲 initRate 的 static 成員函數,做爲 interestRate 初始化式。

注意,儘管 initRate 是私有的,咱們仍然可使用該函數來初始化 interestRate。
像任意的其餘成員定義同樣,interestRate 的定義是在類的做用域中,所以能夠訪問該類的私有成員。
像使用任意的類成員同樣,在類定義體外部引用類的 static 成員時,必須指定成員是在哪一個類中定義的。
然而,static 關鍵字只能用於類定義體內部的聲明中,定義不能標示爲 static。

3.1 特殊的整型 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 數據成員是一個常量表達式。
一樣地,它能夠用在任何須要常量表達式的地方,例如指定數組成員 daily_tbl 的維。
const static 數據成員在類的定義體中初始化時,該數據成員仍必須在類的定義體以外進行定義。
在類內部提供初始化式時,成員的定義沒必要再指定初始值:

// definition of static member with no initializer;
// the initial value is specified inside the class definition
const int Account::period;

3.2 static 成員不是類對象的組成部分

普通成員都是給定類的每一個對象的組成部分。static 成員獨立於任何對象而存在,不是類類型對象的組成部分。
由於 static 數據成員不是任何對象的組成部分,因此它們的使用方式對於非 static 數據成員而言是不合法的。

// static 數據成員的類型能夠是該成員所屬的類類型。
// 非 static 成員被限定聲明爲其自身類對象的指針或引用:
class Bar {
public:
  // ...
private:
  static Bar mem1; // ok
  Bar *mem2; // ok
  Bar mem3; // error
};

// 相似地,static 數據成員可用做默認實參:
class Screen {
public:
  // bkground refers to the static member
  // declared later in the class definition
  Screen& clear(char = bkground);
private:
  static const char bkground = '#';
};

非 static 數據成員不能用做默認實參,由於它的值不能獨立於所屬的對象而使用。
使用非 static 數據成員做默認實參,將沒法提供對象以獲取該成員的值,於是是錯誤的。

 

/************** 面試中常見的有關 static 類成員的問題 ****************/

Question:

什麼是 static 類成員? static 成員的優勢是什麼? 他們與普通成員有什麼不一樣?

Answer:

所謂 static 類成員,指的是其聲明前帶有關鍵字 static 的類成員。
static 類成員不是任意對象的組成部分,但由該類的全體對象所共享。

static 成員的優勢:
static 成員的名字是在累的做用域中,所以能夠避免與其餘類的成員或全局對象名字衝突;
能夠實施封裝,static 成員能夠說是私有成員,兒全局對象不能夠;
經過閱讀程序容易看出 static 成員是與特定類關聯的,這種可見性可清晰的顯示程序猿的意圖。

它與普通成員的不一樣在於:普通成員老是與對象相關聯,是某個對象的組成部分;而 static 成員與類相關聯,由該類的全體對象所共享,不是人以對象的組成部分。

相關文章
相關標籤/搜索