静态成员 - static

对象的内存中包含了成员变量,不同的对象占用不同的内存,这使得不同对象的成员变量相互独立,他们的值不受其他对象的影响。那么有没有哪些属性或者方法是归所有对象拥有的?它就是静态成员。

静态成员就是在成员变量和成员函数前加上 static 关键字。静态成员提供了一个同类对象的共享机制,主要是用来解决对象与对象之间通信的问题。静态成员包括 静态成员变量静态成员函数

静态成员变量a

在一个类中,若将一个成员变量声明为 static,这种成员称为 静态成员变量

与一般的数据成员不同,无论建立了多少个对象,静态成员变量都只有一个静态数据的拷贝,所有的对象都共享这些静态成员变量,都可以引用它。

静态成员变量必须在类中声明,在类外初始化,语法格式如下:

static <数据类型> <静态成员变量名>;

由于初始化是在类外进行的,所以调用时需要添加类名作为前缀,语法格式如下:

<数据类型> <类名>::<静态成员变量名> = 初始值;

静态成员变量既可以通过对象名访问,也可以通过类名访问,但要遵循 privateprotectedpublic 关键字的访问权限限制。

  • 通过对象访问静态成员变量时,调用与普通成员函数没有区别。如果是私有属性,则通过 get/set 方法访问或赋值,如果是公共属性,则可以直接使用 对象名.静态成员变量 的形式。

  • 通过类名访问静态成员变量时,需要添加类名前缀 类名::静态成员变量

例如,Person 类中有一个用于统计创建了多少个对象的静态成员变量 total,代码如下:

#include <iostream>
using namespace std;

class Person {
public:
    // 静态变量只能在类内声明
    static int total;
    // 构造函数
    Person() {
        // 每创建一个对象,total 自增 1
        total++;
        cout << "构造函数执行" << endl;
    }

};

// 静态变量需要在类外初始化
int Person::total = 0;

int main() {
    // 创建两个对象并打印静态属性的值
    Person obj_1, obj_2;
    cout << obj_1.total << endl;

    // 再创建两个对象并通过类名打印静态属性的值
    Person obj_3, obj_4;
    cout << Person::total << endl;

    return 0;
}

静态成员函数

静态成员变量也是有访问权限的,因此,私有权限下的静态成员变量就无法通过类的方式调用,例如,我们在 Person 类中添加静态属性 total 放置在私有权限中:

#include <iostream>
using namespace std;

class Person {
private:
    // 私有静态属性
    static int _total;
public:
    // 构造函数
    Person() {
        // 每创建一个对象,_total 自增 1
        _total++;
        cout << "构造函数执行" << endl;
    }

    // 通过 get 方法获取 _total 的值
    int get_total() {
        return _total;
    }

};

// 静态变量需要在类外初始化
int Person::_total = 0;

int main() {
    // 创建两个对象并打印静态属性的值
    Person obj_1, obj_2;
    // 使用 get 方法可以通过对象调用
    cout << obj_2.get_total() << endl;

    // 再创建两个对象并通过类名打印静态属性的值
    Person obj_3, obj_4;

    // 不能通过类名调用
//    cout << Person::get_total() << endl;

    return 0;
}

虽然我们可以通过使用 get 方法的方式来获取 _total 属性的值,但是,依然不能使用类的方式调用。这个时候,我们就需要使用 静态成员函数

在类定义中,前面有 static 说明的成员函数称为 静态成员函数

静态成员函数使用方式和静态变量一样,同样在对象没有创建前,即可通过类名调用。

静态成员函数主要为了访问静态变量,不能访问普通成员变量(非静态成员)。

静态成员函数可以在类内定义,也可以在类外定义。在类外定义时,不需要添加 static 前缀。

因此,以上代码可以修改成下面这种形式:

#include <iostream>
using namespace std;

class Person {
private:
    // 私有静态属性
    static int _total;
    int age;
public:
    // 构造函数
    Person() {
        // 每创建一个对象,_total 自增 1
        _total++;
        cout << "构造函数执行" << endl;
    }

    // 通过 get 方法获取 _total 的值
    //    static int get_total() {
    //        return _total;
    //    }

    // 类内声明
    static int get_total();

};

// 类外定义,定义时不需要添加 static 前缀
int Person::get_total() {
    // 静态函数不能访问普通成员变量(非静态成员)
    // age += 1;
    return _total;
}

// 静态变量需要在类外初始化
int Person::_total = 0;

int main() {
    // 创建两个对象并打印静态属性的值
    Person obj_1, obj_2;
    // 使用 get 方法可以通过对象调用
    cout << obj_2.get_total() << endl;

    // 再创建两个对象并通过类名打印静态属性的值
    Person obj_3, obj_4;

    // 可以通过类名调用静态函数
    cout << Person::get_total() << endl;

    return 0;
}

注意

最后还有一点需要注意的是,静态成员函数没有 this 指针。