C++靜態成員函數(無師自通)

2020-07-16 10:04:41
通過將關鍵字 static 放置在宣告語句的前面作為字首,可以將類的成員函數宣告為靜態成員函數

靜態成員函數的一般形式為:

static <return type><function name> (<parameter list>)

靜態成員函數通常用於處理類的靜態成員變數。實際上,對於類的成員函數來說,如果它不能存取類的任何非靜態成員,則應該將該函數變成靜態成員函數。

下面的程式演示了靜態成員函數的使用。它要求使用者在輸入部門預算請求之前先輸入總部辦公室的預算請求。Budget 類包含一個名為 mainOffice 的靜態成員函數。該函數將實參新增到靜態 corpBudget 變數中,並在定義 Budget 類的任何範例之前呼叫它。getCorpBudget() 函數為靜態成員函數。
//budget2.h的內容
#ifndef BUDGET_H
#define BUDGET_H
class Budget
{
    private:
        static double corpBudget;
        double divBudget;
    public:
        Budget() { divBudget =0; }
        void addBudget(double b)
        {
            divBudget += b;
            corpBudget += divBudget;
        }
        double getDivBudget() const
        {
            return divBudget;
        }
        static double getCorpBudget()
        {
            return corpBudget;
        }
        static void mainOffice(double);
};
#endif
//budge t2.cpp 的內容
#include "budget2.h"
// Definition of the static member of Budget class.
double Budget::corpBudget = 0;
void Budget::mainOffice(double budReq)
{
    corpBudget += budReq;
}
//main程式的內容
// This program demonstrates a static class member function.
#include <iostream>
#include <iomanip>
#include "budget2.h" // For Budget class declaration
using namespace std;

int main()
{
    const int N_DIVISIONS = 4;
    // Get the budget requests for each division
    cout << "Enter the main office's budget request: ";
    double amount;
    cin >> amount;
    // Call the static member function of the Budget class Budget::mainOffice(amount);
    // Create instances of the Budget class
    Budget divisions[N_DIVISIONS];
    for (int count = 0; count < N_DIVISIONS; count++)
    {
        double bud;
        cout << "Enter the budget request for division ";
        cout << (count + 1) << ": ";
        cin >> bud;
        divisions[count].addBudget(bud);
    }
    // Display the budget for each division
    cout << setprecision (2);
    cout << showpoint << fixed;
    cout << "nHere are the division budget requests:n";
    for (int count = 0; count < N_DIVISIONS; count++)
    {
        cout << "tDivision " << (count + 1) << "t$ ";
        cout << divisions[count].getDivBudget() << endl;
    }
    //Print total budget requests
    cout << "Total Requests (including main office) : $ ";
    cout << Budget::getCorpBudget() << endl;
    return 0;
}
程式輸出結果:

Enter the main office's budget request: 400000
Enter the budget request for division 1: 102000
Enter the budget request for division 2: 210000
Enter the budget request for division 3: 240000
Enter the budget request for division 4: 105000

Here are the divisionbudget requests:
Division 1 $ 102000.00
Division 2 $ 210000.00
Division 3 $ 240000.00
Division 4 $ 105000.00
Total Requests (including main office): $ 1057000.00

請注意呼叫靜態函數 mainOffice 的語句:

Budget::mainOffice(amount);

對靜態成員函數的呼叫,通常通過使用作用域解析運算子將函數名稱連線到類名來完成。如果已經定義了類的物件,那麼靜態成員函數也可以通過使用點運算子將它們的名稱連線到物件來呼叫。因此,此程式的最後一個輸出語句可以寫成以下形式:

cout << divisions[0].getCorpBudget() << endl;

this 指標不能在靜態成員函數中使用,因為靜態成員函數不是通過它們所屬類的任何範例呼叫的。而且,靜態成員函數除非指定該成員屬於哪個範例,否則不能存取其類的範例成員。

例如,來看以下類定義語句:
class StatAccess
{
    private:
        int x;
    public:
        static void output()
        {
            cout << x; //對非靜態成員的不正確存取
        }
    StatAccess(int x) { this->x = x; }
};
在語句 cout<<x 中試圖存取 x 是不正確的,因為它等於隱式使用 this 指標,而這是靜態函數 output 所不具有的。相反,在以下修改過的同一個類的範例中,靜態成員函數 print 正確地存取了非靜態成員 x,因為它使用了傳遞給它的類物件的名稱作為形參來限定它。
class StatAccess
{
    private:
        int x;
    public:
        static void print(StatAccess a)
        {
            cout << a.x;
        }
        StatAccess(int x) { this->x = x; }
};
靜態成員函數的一個優點是可以在任何類的範例被建立之前呼叫它們,這使得它們可以用來執行複雜的初始化任務,這些任務必須在建立類的物件之前完成。

C++ 使用關鍵字 Static 來描述靜態類成員函數。要理解其中原委,可以看一看範例與靜態類成員之間的區別。類的每個物件都有它自己的範例成員的副本,但是所有的物件都共用相同的靜態成員。

與此相似的是,每次呼叫函數都有其自己的非靜態區域性變數的副本,但是所有的函數呼叫都共用相同的靜態區域性變數。在該類比中,函數定義對應類,函數呼叫對應類的物件。