C++中的static
1.过程中的中的static
静态全局变量(在全局变量前加static)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <iostream> using namespace std;
void fn();
static int n; //static globle var
int main()
{ n=20;
cout<<n<<endl;
fn();
} void fn()
{ n++;
cout<<n<<endl;
} |
静态全局变量有以下特点:
- 未经初始化的静态全局变量被程序自动初始化为0;
- 静态全局变量在整个文件中都是可见的,而在文件之外是不可见的;
以上代码中,如果把static去掉,照样运行正常。的确,定义全局变量可以用在整个文件***享,但定义全局变量还有以下好处:
- 静态全局变量不能被其它文件所用,其它文件定义相同的名字不会发生冲突。
注意全局变量和全局静态变量的区别:
- 全局变量不加static修饰,但全局变量默认是静态的,作用于整个工程,在一个文件中定义全局变量,在另一个文件中用extern 全局变量声明,就可以使用全局变量。
- 全局静态变量显示用static修饰,但是他作用于它所在的文件中,对于其它文件不可引用,即使用extern也无法引用它。
静态局部变量(在一个局部变量前加static)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <iostream> using namespace std;
void fn();
void main()
{ fn();
fn();
fn();
} void fn()
{ static int n=10;
cout<<n<<endl;
n++;
} |
通常局部变量在函数完毕后变会被释放,基值不在保存。但是我们如果需要在两次调用的时候保存变量的值,通常的方法定义一个全局变量来实现,但是这样一来,变量不在属于函数本身了,而属于整个文件,给维护带来很多问题。静态局部变量可以很好的解决这个问题。
静态局部变量保存的全局数据区,而不是保存在栈上,每次的值保存到下一次调用,直到下一次赋新值。
静态局部变量有以下特点:
- 该变量在全局数据区分配内存;
- 它在执行到该对象首次声明处被首次初始化,即以后调用函数不再初始化。
- 它一般在声明处初使化,如果没有显示初始化,则被初始化为0。
- 它始终驻留于程序中,直到程序结束运行。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束
静态函数(在函数返回值前面加static)
说明:它与变通函数不同,它只能在声明它的文件中可见,不能被其它文件使用。
好处:
- 不能被其它文件所用;
- 其它文件中定义同名函数,不会发各冲突。
2.面向对象中的static关键字(类中的static)
静态数据成员:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
// static_class_data_member.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #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; //it's a static class data member
}; int Myclass::Sum=0; //definition and initial the static class data member
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 _tmain( int argc, _TCHAR* argv[])
{ Myclass M(1,2,3);
M.GetSum();
Myclass N(4,5,6);
N.GetSum();
M.GetSum();
return 0;
} |
可以看出静态数据成员有以下特点:
- 对于非静态数据成员,第一个类对象都有自己的一份拷贝。而静态类成员被当作是类的成员,无论这个对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型所有对象共享访问。也就是说,静态数据成员间该类的所有对象所共有的,对于类的多个对象来说,静态数据礔 只分配一次内存,供所有对象共用,所以,静态数据成员产的值对每天个对象都是一样的,它的值可以更新。
- 静态数据成员在全局数据区。静态数据成员在定义时要分配空间,所以不能在类声明中定义,在上例中,语句int Myclass::Sum=0;是定义静态数据成员。
- 静态数据成员和普通数据成员一样,遵从public,protected,private访问规则。
- 因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定类对象,在没有产生类对象的时候它的作用域就已经可见了,即在没有产生类实例的时候,我们就可以操作它。
- 静态数据成员与一般的数据初使化不同,格式化为:
- <数据类型><类名>::<成员名>=<值>
- 类的静态数据成员访问有两种形式:
- <类对象名>.<静态数据成员名>或<类类型名>::<静态数据成员>
- 如果静态数据成员的访问权限允许的话(public),按上述格式引用静态数据成员。
- 静态成员变量主要在各个对象都有相同的某项属性的时候。比如对于一个存款类,每一个实例的利息都是相同的,所以应该把利息设为存款类的静态数据成员。这有两个好处和:第一、不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区内存,所以节省存储空间。第二,一但利息需要改变时,只要改变一次就行了。
- 同全局变量相比,使用静态数据成员有两个优势:
- 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性。
- 可以实现信息的隐藏。静态数据成员可以是private成员,而全局变量不能。
静态成员函数
与静态数据成员一样,静态成员函数不是专们为某一相类对象而服务的,而是为此类的全部对象所服务。它不与任意类对象所联系,所以它不具有this指针。从这个意义上讲,它无法访问非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
#include <iostream> using namespace std;
class Myclass
{ public :
Myclass( int a, int b, int c);
static void GetSum(); //static class_member fun
private :
int a,b,c;
static int Sum; //static class_member_data
}; int Myclass::Sum=0; //definition and initialization
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()
{ Myclass M(1,2,3);
M.GetSum();
Myclass N(4,5,6);
N.GetSum();
Myclass::GetSum();
} |
关于静态成员函数,有以下特点:
- 出现在类体外的函数定义不能指定关键字static;
- 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数。
- 静态成员函数不能访问非静态函数和非静态数据成员。
- 由于没有this指针的额外开销,因此静态成员函数与类全局函数相比速度会有少许增长。
- 调用:<类名>::<静态成员函数名>(<参数表>)
作用:
static静态变量声明符。在声明它的程序块,子程序块或函数内部有效,值保持在整个程序期间分配存储品空间,编译器默认值0。
是c++中很常用的修饰符,它被用来控制变量的存储方式和可见性。