一,面向过程的程序设计中的static
静态全局变量
- 变量内存在全局数据区。
- 没有手动初始化的全局变量都会被自动初始化为0。
- 静态全局变量 在声明它的整个文件中都是可见的,在文件之外是不可见的。
一个完整的程序在内存中的分布:代码区,全局数据区,堆区,栈区。
参考代码:
#include<iostream>
using namespace std;
static int n; //定义静态全局变量
void fn()
{
n++;
cout<<n<<endl;
}
int main(void)
{
n = 20;//初始化
cout<<n<<endl;
fn();
return 0;
}
运行结果:
全局变量与静态全局变量比较:
- 全局变量可以实现变量在不同文件中共享
- 静态全局变量变量不能被其他文件所使用
//File1 #include<iostream> using namespace std; void fn(); int n; //定义静态全局变量 ,尝试加上static关键字是否能成功 int main(void) { n = 20; cout<<n<<endl; fn(); return 0; }
//File2 #include<iostream> using namespace std; extern int n; void fn() { n++; cout<<n<<endl; }
静态局部变量
在局部变量前加入static关键字,就成为静态局部变量
特点:
- 静态局部变量在全局数据区
- 静态全局变量在程序执行到该对象的声明处首次初始化,即以后的函数调用不会再初始化
- 静态全局变量一般在声明处初始化,若没有显式初始化,会被程序自动初始化为0
- 静态全库变量始终驻留在全局数据区,直到程序运行结束。
#include<iostream>
using namespace std;
void fn();
int main(void)
{
fn();
fn();
fn();
return 0;
}
void fn()
{
static int n = 10;
cout<<n<<endl;
n++;
}
运行结果:
静态函数
函数类型前面加static关键字,定义为静态函数。静态函数只能在本文件中使用,不能被其他文件所使用。
二,面向对象程序设计中static关键字
静态数据成员
- 对于非静态数据成员,每次定义一个新的对象,都会产生一个新的拷贝。而静态数据成员是类的成员,不管定义多少个这个类的对象,静态数据成员在程序中也只有一份拷贝,即该类型的成员是所有对象所共享的,分配一次内存,所有该类的对象都可以访问,从而它的值是更新的。
- 静态数据成员存储在全局数据区。因为静态数据成员定义是要分配空间,所以不能在类的声明中定义。如下程序,int Myclass::Sum=0;是定义静态数据成员。
- 因为静态数据成员内存在全局数据区,所以在没有类的实例时就可以操作它。
- 静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化格式:<数据类型><类名>::<静态数据成员名>::=<值>。
- 静态数据成员用来存储每个对象都具有的属性。只要改变一次,所有这个类的信息都改变。
- 同全局变量相比,静态数据成员的优势:静态数据成员没有进入全局名字空间,因此不存在与其他全局名字冲突的可能性;可是实现信息的隐藏,静态数据成员可以是private,但全局变量不行。
#include<iostream>
using namespace std;
class Myclass
{
private:
int a , b , c;
static int sum; //声明静态数据成员
public:
Myclass(int a , int b , int c);
void GetSum();
};
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;
}
int main(void)
{
Myclass M(1 , 2 , 3);
M.GetSum();
Myclass N(4 , 5 , 6);
N.GetSum();
M.GetSum();
return 0;
}
静态成员函数
- 与静态变量类似,静态成员函数是为类服务,而不是为类具体某个对象服务,是类的内部实现,属于类的一部分。
- 普通的成员函数一般隐含了this指针,this指针指向类的对象本身,因为普通成员函数是属于具体某个对象的。一般this缺省,如函数fn()实际上是this->fn()。静态成员函数与类的对象没有关系,因此不具有this指针。因此静态成员函数无法访问属于类对象的非静态成员和非静态成员函数,只能调用其余静态成员。
- 非静态成员可以任意调用静态成员,反之则不行。
#include<iostream>
using namespace std;
class Myclass
{
private:
int a , b , c;
static int sum; //声明静态数据成员
public:
Myclass(int a , int b , int c);
static void GetSum(); //声明静态成员函数
};
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<<a<<endl; //错误代码,a是非静态数据成员
cout<<"sum="<<sum<<endl;
}
int main(void)
{
Myclass M(1 , 2 , 3);
M.GetSum();
Myclass N(4 , 5 , 6);
N.GetSum();
Myclass::GetSum();
return 0;
}