回顾一下C语言中static的描述,我们知道:
- 当static修饰局部变量时,使局部变量的生命周期延长
- .static修饰全局变量时,将外部链接属性变成了内部链接属性,使全局变量的作用域只能在该源文件中执行
- .static修饰函数时,将外部链接属性变成了内部链接属性,使函数的作用域只能在该源文件中执行
概念
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用
static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。
类中的成员被static修饰过之后,该成员并不是属于某个对象,而是属于整个类(因为类成员存在静态区)。
我们之前了解过类中的成员函数并不是和成员变量一起存在类创建的对象中的,而是存在公共的代码区里。即每个对象在创建的时候都不用为成员函数单独开辟空间,只需要为非静态成员变量开辟空间。
static修饰成员变量
private:
static int n;//属于整个类里的静态成员,不属于某个对象中
static int m;//声明
这里static修饰的成员变量是不能给初始值的,因为我们知道这里给值的话,在创建对象时,就会走初始化列表,如果初始化列表没有对成员变量的值初始化,而这里恰恰还给了缺省值的话,程序执行的时候自然就会走到这里,用缺省值进行初始化。但是你是用static修饰的静态成员变量,目的不就是为了该静态变量不会受到在类创建对象时的初始化吗,所以就引出:静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
{
private:
static int n;//属于整个类里的静态成员,不属于某个对象中
static int m;//声明
};
int A::m = 0;//定义
int A::n = 0;
private修饰的是变量的作用范围,表示只能在本类中使用。 static修饰的是变量的生命周期,它在类加载时一起被加载,而其他成员变量是在实例化对象时加载的,比其他成员变量要早。
成员访问
那么静态成员变量该怎么访问呢???
我们知道一般成员变量都是设为私有的封装起来,所以成员外的变量是不能随便进行访问的,所以我们可以首先想到“解锁”:类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
我们一般的成员可以通过象.成员进行访问,而静态成员会多出一种访问方式:类名::静态成员,因为前面我们已经知道,静态成员并不是属于某个对象里的私有成员,而是属于整个类里面的,所以我们可以直接通过类名进行访问。
那么还有没有其他方法呢???
另外一种就是在类里再创建一个成员函数,通过访问成员函数去访问类里的成员。
class A
{
public:
A()
{
++m;
++n;
}
void Print()
{
cout << m << " " << n << endl;
}
private:
static int n;//属于整个类里的静态成员,不属于某个对象中
static int m;//声明
};
int A::m = 0;//定义
int A::n = 0;
int main()
{
A a2;
a2.Print();
}
static修饰成员函数
static也是可以修饰函数的,就像上面访问成员其实还有一种方式,可以不创建对象,直接通过类访问:
class A
{
public:
A()
{
++m;
++n;
}
static void Print()//静态成员函数(没有this指针)所以不能访问非静态成员
{
cout << m << " " << n << endl;
}
private:
static int n;//属于整个类里的静态成员,不属于某个对象中
static int m;//声明
};
int A::m = 0;//定义
int A::n = 0;
int main()
{
A::Print();
}
同理可以了解到,static修饰的成员函数也是属于整个类里面的,所以可以直接通过类名去访问成员函数的。所以同时就引出:静态成员函数没有隐藏的this指针,不能访问任何非静态成员
这是因为你在调用静态成员函数的时候,实际上是通过类名调用的(即使你用对象调用),所以传参的时候就不会隐式的传对象的指针,所以就没有this指针变量,因此就不可以在函数内访问类里的非静态成员。
最后一点就是:静态成员也是类的成员,受public、protected、private 访问限定符的限制