C++静态成员函数(无师自通)

通过将关键字 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 来描述静态类成员函数。要理解其中原委,可以看一看实例与静态类成员之间的区别。类的每个对象都有它自己的实例成员的副本,但是所有的对象都共享相同的静态成员。

与此相似的是,每次调用函数都有其自己的非静态局部变量的副本,但是所有的函数调用都共享相同的静态局部变量。在该类比中,函数定义对应类,函数调用对应类的对象。