C++中static关键字作用总结Word文件下载.docx
《C++中static关键字作用总结Word文件下载.docx》由会员分享,可在线阅读,更多相关《C++中static关键字作用总结Word文件下载.docx(14页珍藏版)》请在冰点文库上搜索。
对于一个完整的程序,在内存中分为代码区,全局数据区,堆区,栈区。
一般程序中由new产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。
自动变量一般会随着函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量)也存放在全局数据区。
全局数据区的数据并不会因为函数的退出而释放空间。
细心的读者可能会发现,Example1中的代码中将
//定义静态全局变量
改为
intn;
//定义全局变量
程序照样正常运行。
的确,定义全局变量就可以实现变量在文件中的共享,但定义静态全局变量还有以下好处:
静态全局变量不能被其它文件所用;
其它文件中可以定义相同名字的变量,不会发生冲突;
可以将上述示例代码改为如下:
//Example2
//File1
voidmain()
{
n=20;
n<
//File2
externintn;
编译并运行Example2,您就会发现上述代码可以分别通过编译,但运行时出现错误。
试着将
改为
//定义全局变量
再次编译运行程序,细心体会全局变量和静态全局变量的区别(验证共享和保护关系)。
2、静态局部变量
在局部变量前,加上关键字static,该变量就被定义成为一个静态局部变量。
我们先举一个静态局部变量的例子,如下:
//Example3
staticn=10;
通常,在函数体内定义了一个变量,每当程序运行到该语句时都会给该局部变量分配栈内存。
但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效。
但有时候我们需要在两次调用之间对变量的值进行保存。
通常的想法是定义一个全局变量来实现。
但这样一来,变量已经不再属于函数本身了,不再仅受函数的控制,给程序的维护带来不便。
静态局部变量正好可以解决这个问题。
静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。
静态局部变量有以下特点:
b.静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
c.静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;
它始终驻留在全局数据区,直到程序运行结束。
但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;
3、静态函数
在函数的返回类型前加上static关键字,函数即被定义为静态函数。
静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用。
静态函数的例子:
//Example4
staticvoidfn();
//声明静态函数
fn();
voidfn()//定义静态函数
intn=10;
cout<
定义静态函数的好处:
a.静态函数不能被其它文件所用;
b.其它文件中可以定义相同名字的函数,不会发生冲突;
二、面向对象程序设计中的static
1、类中的普通成员
类中的成员变量和成员函数是分开存储的。
其中,
1)每个对象都有独立的成员变量;
成员变量可以存储在栈空间、堆空间、全局数据区;
2)所有对象共享类的成员函数;
成员函数只能存储在代码段;
2、类中的静态成员(static)
类中的静态成员
1、用static关键字修饰;
2、可以用类名:
:
成员名访问静态成员;
3、静态成员属于整个类;
4、静态成员是所属类的成员,其它类不能访问;
5、静态成员的内存分配是唯一的;
1)静态成员变量
特征:
1、静态成员变量属于整个类所有;
2、静态成员变量的生命周期不依赖任何对象;
(静态成员变量的生命周期在程序的运行期)
3、所有对象共享类的静态成员变量;
4、可以通过类名直接访问公有的静态成员变量;
5、可以通过对象名访问公有的静态成员变量;
6、静态成员变量需要在类外单独分配空间;
(类内声明、类外定义并初始化)
7、静态成员变量在程序内部位于全局数据区,不计入类的内存计算。
原因/好处:
使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。
使用方法:
1、在类的内部,使用static修饰普通成员变量;
2、在类的外部(全局作用域),使用TypeClassName:
VarName=value初始化,并申请存储空间;
注:
静态成员变量不属于类的任何对象,所以并不是对象建立时被定义的,所以它不能由类的构造函数初始化,一般也不能在类内初始化;
/*
静态成员变量只能在类的内部声明,在类的外部(全局区)定义和初始化;
*/
iostream>
usingnamespacestd;
classTest{
public:
intGetA()const{returna;
private:
staticinta;
//静态成员变量
};
//intTest:
a;
如果这样定义不赋予初值,则初值为零
intTest:
a=1;
intmain(intargc,char*argv[])
TestT;
cout<
T.GetA()<
endl;
return0;
静态成员变量被类的所有对象共享,包括派生类对象;
classBase{
//intTest:
intBase:
classDerived:
publicBase{
BaseB;
DerivedD;
B.a++;
cout<
B.a<
//1
D.a++;
D.a<
//2
return0;
静态成员变量可以作为普通成员函数的默认形参,而普通成员变量则不可以;
classTest{
//静态成员变量
intb;
voidfun_1(inti=a);
//正确
//voidfun_2(inti=b);
//报错
静态成员变量的类型可以是所属类的类型,而普通成员变量则不可以。
普通成员变量只能声明为所属类类型的指针或引用;
staticTesta;
Testb;
Test*pTest;
Test&
m_Test;
staticTest*pStaticObject;
静态成员变量在const函数中可以修改,而普通的成员变量是万万不能修改的;
const修饰的是当前this指针所指向的对象是const,但是静态成员变量不属于任何类的对象,它被类的所有对象修改,所以this指针不修饰静态的成员变量,所以可以更改。
Test():
b(0){}
voidtest()const
{
a++;
//b++;
//err//const指的是不能修改当前调用该函数对象的成员变量
}
2)静态成员函数
1、静态成员函数属于整个类所有;
2、所有对象共享类的静态成员函数;
3、可以通过类名直接访问公有的静态成员函数;
4、可以通过对象名访问公有的静态成员函数;
5、静态成员函数只能访问静态成员,不能访问非静态成员;
6、静态成员函数没有this指针,也就是说静态成员函数不能使用修饰符(也就是函数后面的const关键字);
原因:
处理静态成员变量;
直接用static修饰普通成员函数(类内声明时),不需要static修饰(类外定义时);
总结:
案例分析:
/**
*统计某班选修课考试的平均成绩
string>
classStudent
stringname;
//姓名
stringgender;
//性别
floatscore;
//分数
stringsubject;
//课程
staticinttotal_counts;
//总人数
staticfloatchinese_scores;
//语文分数
staticintchinese_counts;
//语文课人数
staticfloatmath_scores;
//数学分数
staticintmath_counts;
//数学课人数
Student(stringname,stringgender,floatscore,stringsubject);
~Student();
staticfloataveScores(stringsubject);
voidprintStudentInfo();
voidprintAveScores();
intStudent:
total_counts=0;
floatStudent:
chinese_scores=0;
chinese_counts=0;
math_scores=0;
math_counts=0;
Student:
Student(stringname,stringgender,floatscore,stringsubject)
this->
name=name;
gender=gender;
score=score;
subject=subject;
If(subject=="
chinese"
||subject=="
语文"
)
chinese_scores+=score;
chinese_counts++;
elseif(subject=="
math"
数学"
math_scores+=score;
math_counts++;
else
"
thisisnothesubect:
"
<
subject<
total_counts+=(chinese_counts+math_counts);
~Student()
total_counts--;
chinese_counts--;
math_counts--;
aveScores(stringsubject)
floatave_score=0;
If(chinese_counts>
0&
&
subject=="
ave_score=(chinese_scores/chinese_counts);
//cout<
\t"
chinese_counts<
chinese_scores<
elseif(math_counts>
ave_score=(math_scores/math_counts);
math_counts<
math_scores<
returnave_score;
voidStudent:
printStudentInfo()
name<
gender<
score<
printAveScores()
subject<
averagescore:
aveScores(subject)<
intmain(intargc,charconst*argv[])
constintSIZE=5;
Studentstu[SIZE]=
Student("
10001"
"
male"
92,"
),
10002"
91,"
10003"
10004"
93,"
10005"
};
for(inti=0;
i<
SIZE;
i++)
stu[i].printStudentInfo();
stu[0].printAveScores();
stu[1].printAveScores();
Student:
aveScores("
)<