之前写了一篇面向过程的static,现在来认识一下面向过程的static。面向过程的static主要体现在三个方面。修饰全局变量,修饰局部变量和修饰函数。在面向对象中,主要体现在以下两方面:
修饰成员变量
用法:声明时在成员变量类型前加static。初始化时要在类外进行。
class A
{
private:
static int a;//声明静态成员变量a;
};
int A::a=0;//初始化静态成员变量a;
改变: 存储位置发生改变,他的数据会保存在数据段中(有一些文章会写存入全局数据区,静态数据区的,首先全局数据区就是静态数据区,他们都位于数据段)。这将发生一系列连锁的变化。
在定义时就要为静态成员变量分配内存空间,类只有在实例化时才会分配空间,所以不能在类内定义。
对于非静态成员变量,每个类对象都有自己的拷贝,分配不同的内存空间。而静态成员变量被当作是类的成员。无论这个类的对象被定义了多少个,静态成员变量在程序中也只有一份,只占据一块内存空间,由该类型的所有对象共享访问。所以静态成员变量在每个对象中都是一样的。
因为静态成员变量在数据段分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它。
如果静态成员变量的访问权限允许的话(即public的成员),可在程序中引用静态成员变量:
<类对象名>.<静态成员变量名> 或 <类类型名>::<静态成员变量名>
未变: 静态数据成员和普通数据成员一样遵从public,protected,private访问规则;
作用: 一个类声明的对象中,静态成员变量是可以当全局变量使的。或在继承中,如果在基类中声明一个静态成员变量。那么,在基类和子类所声明的对象中,这个静态成员变量可以有和全局变量有一样的功效。而且还比全局变量有优势。
静态成员变量相较全局变量的优势:
1. 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性。
2. 可以封装,实现信息隐藏。静态数据成员可以是private成员,而全局变量不能。
修饰成员函数
用法:声明时在返回值类型前加static,定义时不能加。调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以直接使用如下格式:
<类名>::<静态成员函数名>(<参数表>)
class A
{
public:
static void function();//声明静态成员函数
};
//定义静态成员函数
void A::function()
{
……
}
//调用静态成员函数
A a;
a.function();
A::function();
改变:在类的内部实现,也就是说该类的全部服务而不是为某一个类的具体对象服务。正因如此它也没有this指针。
普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this是缺省的。如函数fn()实际上是this->fn()。
由于没有this指针它无法访问属于类对象的非静态成员变量,也无法访问非静态成员函数,它只能调用其余的静态成员函数。
未变:还是可以被非静态成员函数任意地访问。
作用:由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长。
#include<iostream>
using namespace std;
class A
{
public:
A(int x,int y):a(x),b(y){}
int GetSum();
static void PrintSum();
private:
int a,b;
static int sum;
};
int A::sum=0;
int A::GetSum()
{
return sum=a+b;
}
void A::PrintSum()
{
cout<<sum<<endl;
}
int main()
{
A a1(1,2);
A a2(2,3);
cout<<a1.GetSum()<<endl;
cout<<a2.GetSum()<<endl;
a1.PrintSum();
A::PrintSum();
return 0;
}
输出结果:
3
5
5
5
总结
其实static关键字给所修饰对象带来的最大改变就是存储位置的改变,所以内存区段的划分对我们理解编程还是有着很重要的意义的。