static作用解析
前言
static是存储方式的一种,在c++中static有两种用法:
- 面向过程程序设计
- 面向对象程序色设计
其实概括起来,static的作用就是使被它所修饰的词的生存期变长,还有就是私密性这里后面再介绍。
然后对于这个还要了解一下内存分布情况:
- 栈区: 由编译器自动分配释放,像局部变量,函数参数,都是在栈区。会随着作用于退出而释放空间。
- 堆区:程序员分配并释放的区域,像malloc©,new(c++)所申请的空间就是在堆区。
- 全局数据区(静态区):全局变量和静态便令的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束释放。
- 代码区,用于储存代码。
面向过程程序设计
静态变量
在用static修饰变量时,此变量有一下特性:
- 该变量保存在静态存储区,在程序结束时才被销毁。
- 如果该变量没有进行赋予初始值,被static修饰时会有初始值0。
//第一个文件
#include<iostream.h>
static int n;
int main(){
n=5;
while(n--)
cout<<n--<<endl;
}
//第二个文件
#include<iostream.h>
extern int n;//extern 的意思是引用外面文件中的变量。
int main(){
n=5;
while(n--)
cout<<n--<<endl;
}
这样第二个文件运行时会出错,但是如果把第一个文件中n的定义改为int n,这样就可以运行了。
这里呢,定义静态全局变量的好处就是:静态全局变量不能被其他文件所用,而且其他文件中定义相同名字的变量会相互不影响。
然后再看看两个程序:
#include <iostream.h>
void f();
void g();
int main()
{
f();
g();
f();
g();
}
void f()
{
static n=10;
cout<<"f="<<n<<endl;
n++;
}
void f()
{
j=10;
cout<<"g="<<j<<endl;
j++;
}
//输出:
f=10;
g=10;
f=11;
g=10;
静态函数的作用和静态变量的作用差别不大。在定义之后也不能被外部文件通过extern进行引用。
面向对象编程程序设计
静态数据成员
- 静态数据成员脱离具体对象而独立存在,其存储空间是独立分配的,所以就算类没有任何对象的时候它都可以访问。
- 静态数据成员是一种特殊的数据成员,它为类属性,而不是某个对象单独的属性,这里是因为它保存在全局变量区,然后生存期比实体都长,所以这是类的属性。
- 在类中只能进行声明,不能定义。定义只能在外面进行。
- 静态数据成员可以作为成员函数的默认形参,而普通数据成员则不可以
class Test{
public:
static int a;
int b;
void fun_1(int i = a);//正确
void fun_2(int i = b);//报错
};
- 静态数据成员的类型可以是所属类的类型,而普通数据成员则不可以。普通数据成员的只能声明为 所属类类型的 指针或引用
class Test{
public:
static Test a;//正确
Test b;//报错
Test *pTest;//正确
Test &m_Test;//正确
static Test *pStaticObject;//正确
};
static修饰后对比:
#include <iostream>
using namespace std;
class Myclass
{
public:
Myclass(int a,int b,int c);
void GetSum();
private:
int a,b,c;
static int Sum;
};
int Myclass::Sum=0;
Myclass::Myclass(int a,int b,int c)
{
this->a=a;
this->b=b;
this->c=c;
Sum+=a+b+c;
}
void Myclass::GetSum()
{
cout<<"Sum="<<Sum<<endl;
}
void main()
{
Myclass M(1,2,3);
M.GetSum();
Myclass N(4,5,6);
N.GetSum();
M.GetSum();
}
/*输出结果:
Sum=6
Sum=21
Sum=21
如果把static去掉的话。
输出结果会是:
Sum=6
Sum=15
Sum=6*/
静态数据函数
特点:
- 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数
- 非静态成员函数可以任意地访问静态成员函数和静态数据成员
- 静态成员函数不能访问非静态成员函数和非静态数据成员
- 调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以用类名::函数名调用(因为他本来就是属于类的,用类名调用很正常)
这里有个疑问,为什么静态成员函数不能访问非静态函数和成员,但时非静态可以访问静态。因为静态成员函数是属于类的,所以这个函数不知道到底有多少个对象,所以就无法访问。然后反过来,创建的对象对类是知道的,就可以直接使用类里面的函数。所以会有这个结果。