type
status
date
slug
summary
tags
category
icon
password
Property
有的时候类需要他的一些成员与类本身直接相关,而不是与类的各个对象保持关联。
声明为 static的类成员称为 类的静态成员。用 static修饰的 成员变量,称之为 静态成员变量;用 static修饰的 成员函数,称之为 静态成员函数。静态的成员变量一定要在类外进行初始化。
权限可以被缩小但不能被放大,静态成员函数不可以调用非静态成员函数,非静态成员函数可以调用类的静态成员函数。
声明静态成员
使用关键字
static
可以声明类的静态成员,可以是public
或private
的。静态数据成员的类型可以是常量、引用、指针、类类型等。类的静态成员存在于任何对象之外,对象中不包含与静态成员相关的数据。因此每个
Account
对象将包含两个数据成员:owner
和amount
。只存在一个interestRate
对象而且被所有的Account
对象共享。类似的,静态成员函数也不与任何对象绑定在一起,它们不包含
this
指针。由于静态成员不与任何对象绑定,因此静态成员函数不能声明为const
的,也不能在静态成员函数内使用this
指针。使用类的静态成员
可以使用作用域运算符访问静态成员,也可以通过类对象、引用或指针访问。类的成员函数可以直接访问静态成员。
定义静态成员
和其他成员函数一样,既可以在类的内部也可以在类的外部定义静态成员函数。在类外部定义静态成员时,不能重复
static
关键字,该关键字只能用于类内部的声明语句:和类的所有成员一样,当指向类外部的静态成员时,必须指明成员所属的类名。
static
关键字则只出现在类内部的声明语句中。因为静态数据成员不属于类的任何一个对象,因此它们并不是在创建类对象时被定义的。通常情况下,不应该在类内部初始化静态成员。而必须在类外部定义并初始化每个静态成员。一个静态成员只能被定义一次。一旦它被定义,就会一直存在于程序的整个生命周期中。
C++11支持非静态成员变量在声明时,直接初始化。静态成员变量必须在类外定义,定义时不添加
static
关键字。静态成员跟类走不跟对象走,类在他在,而一般成员是对象在他才在;所以静态成员可以通过类名直接调用,而普通成员必须通过对象调用。
实现一个类,计算中程序中创建出了多少个类对象:
类似于全局变量,静态数据成员定义在任何函数之外。因此一旦它被定义,就将一直存在于程序的整个生命周期中。
定义静态数据成员的方式和在类的外部定义成员函数差不多。需要指定对象的类型名,然后是类名、作用域运算符以及成员自己的名字:
建议把静态数据成员的定义与其他非内联函数的定义放在同一个源文件中,这样可以确保对象只被定义一次。
静态成员的类内初始化
尽管在通常情况下,不应该在类内部初始化静态成员。但是可以为静态成员提供
const
整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的 constexpr
。初始值必须是常量表达式,因为这些成员本身就是常量表达式, 所以它们能用在所有适合于常量表达式的地方。
如果某个静态成员的应用场景仅限于编译器可以替换它的值的情况,则一个初始化的
const
或constexpr static
不需要分别定义。相反,如果将它用于值不能替换的场景中,则该成员必须有一条定义语句。例如,如果
period
的唯一用途就是定义daily_tbl
的维度,则不需要在Account
外面专门定义period
。此时,如果忽略了这条定义,那么对程序非常微小的改动也可能造成编译错误,因为程序找不到该成员的定义语句。例如,当需要把Account::period
传递给一个接受const int&
的函数时,必须定义period
。如果在类的内部提供了一个初始值,则成员的定义不能再指定一个初始值了:
即使一个常量静态数据成员在类内部被初始化了,通常情况下也应该在类的外部定义一下该成员。
静态成员能用于某些场景,而普通成员不能
静态成员独立于任何对象。因此,在某些非静态数据成员可能非法的场合,静态成员却可以正常地使用。例如,静态数据成员可以是不完全类型。
特别的, 静态数据成员的类型可以就是它所属的类类型。而非静态数据成员则受到限制,只能声明成它所属类的指针或引用:
静态成员和普通成员的另外一个区别是可以使用静态成员作为默认实参:
非静态数据成员不能作为默认实参,因为它的值本身属于对象的一部分, 这么做的结果是无法真正提供一个对象以便从中获取成员的值,最终将引发错误。