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++中很常用的修饰符,它被用来控制变量的存储方式和可见性。