1、C+中static关键字作用总结C+中static关键字作用总结C+因为兼容C语言,所以其中的static也有两种用法:面向过程程序设计中的static(C语言特性)和面向对象程序设计中的static(C+语言特性)。前者应用于普通变量和函数,不涉及类;后者主要说明static在类中的作用。一、面向过程设计中的static1、静态全局变量在全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量。我们举一个静态全局变量的例子,如下:/ Example 1 #include void fn(); static int n; /定义静态全局变量 void main() n = 20;
2、 cout n endl; fn(); void fn() n+; cout n endl; 静态全局变量有以下特点: a.该变量在全局数据区分配内存; b.未经初始化的静态全局变量会被程序自动初始化为0(自动变量的值是随机的,除非它被显式初始化); c.静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的;静态变量都在全局数据区分配内存,包括后面将要提到的静态局部变量。对于一个完整的程序,在内存中分为代码区,全局数据区,堆区,栈区。一般程序中由new产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。自动变量一般会随着函数的退出而释放空间,静态数据(即使是函数内部的静态局部变
3、量)也存放在全局数据区。全局数据区的数据并不会因为函数的退出而释放空间。细心的读者可能会发现,Example 1中的代码中将static int n; /定义静态全局变量改为int n; /定义全局变量程序照样正常运行。的确,定义全局变量就可以实现变量在文件中的共享,但定义静态全局变量还有以下好处:静态全局变量不能被其它文件所用;其它文件中可以定义相同名字的变量,不会发生冲突;可以将上述示例代码改为如下:/ Example 2/ File1#include void fn();static int n; /定义静态全局变量void main() n=20; coutnendl; fn();/F
4、ile2#include extern int n;void fn() n+; coutnendl;编译并运行Example 2,您就会发现上述代码可以分别通过编译,但运行时出现错误。 试着将 static int n; /定义静态全局变量 改为 int n; /定义全局变量 再次编译运行程序,细心体会全局变量和静态全局变量的区别(验证共享和保护关系)。 2、静态局部变量在局部变量前,加上关键字static,该变量就被定义成为一个静态局部变量。 我们先举一个静态局部变量的例子,如下:/Example 3#include void fn();void main() fn(); fn(); fn(
5、);void fn() static n=10; coutnendl; n+;通常,在函数体内定义了一个变量,每当程序运行到该语句时都会给该局部变量分配栈内存。但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效。但有时候我们需要在两次调用之间对变量的值进行保存。通常的想法是定义一个全局变量来实现。但这样一来,变量已经不再属于函数本身了,不再仅受函数的控制,给程序的维护带来不便。静态局部变量正好可以解决这个问题。静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。静态局部变量有以下特点: a.该变量在全局数据区分配内存; b.静态局部变量在程序执行
6、到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化; c.静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;3、静态函数在函数的返回类型前加上static关键字,函数即被定义为静态函数。静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用。静态函数的例子: /Example 4#include static void fn();/声明静态函数void main()fn();void fn()/定义静态函数int n=10;c
7、outnendl;定义静态函数的好处: a.静态函数不能被其它文件所用; b.其它文件中可以定义相同名字的函数,不会发生冲突;二、面向对象程序设计中的static1、类中的普通成员类中的成员变量 和 成员函数 是分开存储的。其中,1)每个对象都有独立的成员变量;成员变量可以存储在 栈空间、堆空间、全局数据区;2)所有对象共享类的成员函数;成员函数 只能存储在 代码段;2、类中的静态成员(static)类中的静态成员1、用 static关键字 修饰;2、可以用 类名:成员名 访问 静态成员;3、静态成员 属于 整个类;4、静态成员 是所属类的成员,其它类不能访问;5、静态成员的内存分配 是 唯一
8、的;1) 静态成员变量特征:1、静态成员变量 属于 整个类所有;2、静态成员变量的生命周期不依赖任何对象;(静态成员变量的生命周期在程序的运行期)3、所有对象共享类的静态成员变量;4、可以通过 类名 直接访问公有的静态成员变量;5、可以通过 对象名 访问公有的静态成员变量;6、静态成员变量 需要在类外单独分配空间;(类内声明、类外定义并初始化)7、静态成员变量 在程序内部位于全局数据区,不计入类的内存计算。原因/好处:使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。使用方法:1、在类的内部,使用 static 修饰普通成员变量;2、在类的外部(全局作用
9、域),使用 Type ClassName:VarName = value 初始化,并申请存储空间;注:静态成员变量不属于类的任何对象,所以并不是对象建立时被定义的,所以它不能由类的构造函数初始化,一般也不能在类内初始化;/*静态成员变量 只能在类的内部声明,在类的外部(全局区)定义和初始化;*/#include using namespace std;class Test public: int GetA() const return a;private: static int a; / 静态成员变量;/int Test:a;如果这样定义不赋予初值,则初值为零int Test:a = 1;in
10、t main(int argc, char *argv)Test T;cout T.GetA() endl;return 0;静态成员变量 被类的所有对象共享,包括派生类对象;#include using namespace std;class Basepublic: static int a; / 静态成员变量;/ int Test:a;如果这样定义不赋予初值,则初值为零int Base:a;class Derived : public Base;int main(int argc, char *argv) Base B; Derived D; B.a+; cout B.a endl; /
11、1 D.a+; cout D.a endl; / 2 return 0;静态成员变量可以作为普通成员函数的默认形参,而普通成员变量则不可以;class Testpublic: static int a; /静态成员变量 int b; void fun_1(int i = a); /正确 /void fun_2(int i = b); /报错;静态成员变量的类型 可以是所属类的类型,而普通成员变量则不可以。普通成员变量只能声明为 所属类类型的 指针或引用;class Testpublic: static Test a; /正确 Test b; /报错 Test *pTest; /正确 Test
12、&m_Test; /正确 static Test *pStaticObject; /正确;静态成员变量在const函数中可以修改,而普通的成员变量是万万不能修改的;/*const修饰的是当前this指针所指向的对象是const,但是静态成员变量不属于任何类的对象,它被类的所有对象修改,所以this指针不修饰静态的成员变量,所以可以更改。*/class Testpublic: static int a; int b;public: Test():b(0) void test() const a+; /b+; / err / const指的是不能修改当前调用该函数对象的成员变量 ;int Test
13、:a;2)静态成员函数特征:1、静态成员函数 属于 整个类所有;2、所有对象共享类的静态成员函数;3、可以通过 类名 直接访问公有的静态成员函数;4、可以通过 对象名 访问公有的静态成员函数;5、静态成员函数 只能 访问静态成员,不能访问 非静态成员;6、静态成员函数没有this指针,也就是说静态成员函数不能使用修饰符(也就是函数后面的const关键字);原因:处理静态成员变量;使用方法:直接用 static 修饰 普通成员函数(类内声明时),不需要 static 修饰(类外定义时);总结:案例分析:/* 统计某班选修课考试的平均成绩*/#include #include using name
14、space std;class Studentprivate: string name; / 姓名 string gender; / 性别 float score; / 分数 string subject; / 课程 static int total_counts; / 总人数 static float chinese_scores; / 语文分数 static int chinese_counts; / 语文课人数 static float math_scores; / 数学分数 static int math_counts; / 数学课人数public: Student(string na
15、me, string gender, float score, string subject); Student(); static float aveScores(string subject); void printStudentInfo(); void printAveScores();int Student:total_counts = 0;float Student:chinese_scores = 0;int Student:chinese_counts = 0;float Student:math_scores = 0;int Student:math_counts = 0;St
16、udent:Student(string name, string gender, float score, string subject) this-name = name; this-gender = gender; this-score = score; this-subject = subject; If (subject = chinese | subject = 语文) chinese_scores += score; chinese_counts+;else if(subject = math | subject = 数学) math_scores += score; math_
17、counts+; else cout this is no the subect: subject 0 & subject = chinese | subject = 语文) ave_score = (chinese_scores / chinese_counts); /cout subject t chinese_counts t chinese_scores 0 & subject = math | subject = 数学) ave_score = (math_scores / math_counts); /cout subject t math_counts t math_scores
18、 endl; return ave_score;void Student:printStudentInfo() cout name t gender t score t subject endl;void Student:printAveScores() cout subject average score: aveScores(subject) endl;int main(int argc, char const *argv) const int SIZE = 5; Student stuSIZE = Student(10001, male, 92, 语文), Student(10002,
19、male, 91, 数学), Student(10003, male, 91, 数学), Student(10004, male, 93, 语文), Student(10005, male, 92, 语文), ; for(int i = 0; i SIZE; i+) stui.printStudentInfo(); stu0.printAveScores(); stu1.printAveScores(); cout 语文 average score: Student:aveScores(语文) endl; cout 数学 average score: Student:aveScores(数学) endl; return 0;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1