static的三种用法,定义静态变量,静态函数,静态代码块!
1、定义静态变量
class PersonStatic
{
//静态变量的特点
//1.静态变量无需生成对象就可被调用,可以使用类名和对象两种方法调用
//2.静态变量是全局变量
//3.任何一个对象修改静态变量的值,那么所有的该类的对象的静态成员变量的值都改变
static int i;
String name;

2、静态函数
//静态函数的特点
//1.静态函数无需生成对象就可被调用
//2.静态函数不能直接调用非静态的成员变量
//3.不能使用this引用
static void fun()
{
System.out.println("我是静态函数,我的i值为 " + i);
}
/*static void talk()
{
System.out.println("My name is " + name);//此时会出错
}*/

3、静态代码块
//静态代码块
//静态代码块在装载类的时候就被执行,主要为静态成员变量赋初值
static{
System.out.println("我是静态代码块");
}

}

/******************************************************************************************************************************/

数据成员可以分为静态变量、非静态变量两种。

(1)静态成员:静态类中的成员加入static修饰符,即是静态成员,可以使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以 静态成员不能访问非静态成员,因为静态成员存在于内存,所以非静态成员可以直接访问类中的静态成员。

(2)非静态成员:所以没有加static的成员都是非静态成员,当类被实例化后,可以通过实例化的类名进行访问,非静态成员的生存期决定于该类的生存期,而静态成员则不存在生存期的概念,因为静态成员始终驻留在内存中。

一个类中可以包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数。

以下分两方面来说,第一方面主要是相对于面向过程而言,在这方面不涉及类;另一方面相对于面向对象来说,主要说明static在类中的作用。

一、在面向过程设计中的static关键字

1、静态全局变量

定义:在全局变量前加上关键字static,该变量就被定义成一个静态全局变量。

特点:

A 、该变量在全局数据区分配内存

B、初始化:如果不显式初始化,那么将被饮食初始化为0(自动变量是随机的,除非是显式初始化)

C、该变量只在本源文件可见,严格地讲,应该从定义之处开始到本文件结束。

Example 1

[cpp] view plaincopy
  1. #include <iostream>
  2. using namespace std;
  3. void fun();
  4. static int n;
  5. void main()
  6. {
  7. n = 20;
  8. cout<<n<<endl;
  9. fun();
  10. }
  11. void fun()
  12. {
  13. n++;
  14. cout<<n<<endl;
  15. }

D、文件作用域下声明的const的常量默认为static存储类型。

静态变量都在全局数据区分配内存,包括静态局部变量。对于一个完整的程序,在内存中的分布情况如下:

(1)代码区

(2)全局数据区

(3)堆区

(4)栈区

一般在程序中,由new产生的动态数据区放在堆区中,函数内部的自动变量存放在栈区。自动变量一般会随着函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量)也存放在全局数据区中。全局数据区的数据并不会因为函数的退出而释放空间。

如果把Example 1中的

static int n;修改为

int n;//全局变量。它可以实现变量在文件中的共享

但是静态全局变量有以下好处:

在其他文件中可以定义相同名字的变量,而不会发生冲突。

Example 2

[cpp] view plaincopy
  1. FILE 1
  2. #include <iostream>
  3. using namespace std;
  4. void fun();
  5. static int n;
  6. void main()
  7. {
  8. n = 20;
  9. cout<<n<<endl;
  10. fun();
  11. }
  12. FILE 2
  13. #include <iostream>
  14. using namespace std;
  15. extern int n;
  16. void fun()
  17. {
  18. n++;
  19. cout<<n<<endl;
  20. }

2、静态局部变量

定义:在局部变量前加上static关键字时,就定义了静态局部变量。

[cpp] view plaincopy
  1. FILE 3
  2. #include <iostream>
  3. using namespace std;
  4. void fun();
  5. void main()
  6. {
  7. fun();
  8. fun();
  9. fun();
  10. }
  11. void fun()
  12. {
  13. static int n = 10;
  14. n++;
  15. cout<<n<<endl;
  16. }

通常,在函数体内定义了一个变量,每当程序运行到该语句时都会给该局部变量分配栈内存,但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效。但是有时候我们需要在两次调用之间对变量的值进行保存,通常的想法是定义一个全局变量来实现,但是这样一来,变量已经不再属于函数本身了,不再仅受函数的控制,给程序的维护带来不便。

静态局部变量正好可以解决这个问题。静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。

特点:

A、该变量在全局数据区分配内存

B、初始化:如果不是显式初始化,那么将被隐式初始化为0,以后的函数调用不再进行初始化。

C、它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域。当定义它的函数或语句块结束                    时,其作用域也随之结束。

3、静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其他文件使用。

Example 4

[cpp] view plaincopy
  1. FILE 4
  2. #include <iostream>
  3. using namespace std;
  4. static void fun();
  5. void main()
  6. {
  7. fun();
  8. }
  9. void fun()
  10. {
  11. int n = 10;
  12. n++;
  13. cout<<n<<endl;
  14. }

定义静态函数的好处:静态函数不能被其他文件使用。在其他文件中可以定义相同名字的函数,不会发生冲突。

二、面向对象的static关键字

1、静态数据成员

在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。

[cpp] view plaincopy
  1. #include <iostream>
  2. using namespace std;
  3. class MyClass
  4. {
  5. public:
  6. MyClass(int a, int b, int c);
  7. void fun();
  8. private:
  9. int a,b,c;
  10. static int sum;//声明静态数据成员
  11. };
  12. int MyClass::sum = 0;
  13. MyClass::MyClass(int a, int b, int c)
  14. {
  15. this->a = a;
  16. this->b = b;
  17. this->c = c;
  18. sum += a+b+c;
  19. }
  20. void MyClass::fun()
  21. {
  22. cout<<"sum = "<<sum<<endl;
  23. }
  24. void main()
  25. {
  26. MyClass M(1,2,3);
  27. M.fun();
  28. MyClass N(4,5,6);
  29. N.fun();
  30. }

从以上的程序可以看出,静态数据成员有以下特点:

(1)对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。即静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新。

(2)静态数据成员存储在全局数据区,静态数据成员定义时要分配空间,所以不能在类声明中定义。应该在类外定义。

(3)静态数据成员和普通数据成员一样遵从public、private、protected访问规则。

由于静态数据成员在全局数据区分配内存,属于本类的所有对象共享,它不属于特定的类对象,在没有产生类对象时作用域就可见。即在没有产生类的实例时,我们就可以操作它。

静态数据成员的初始化与一般数据成员的初始化不同,即它的初始化格式为:

<数据类型><类名>::<静态数据成员> = <值>

类的静态数据成员有两种访问方式:

如果静态数据成员的访问权限允许的话,即为public成员,可在程序中,按上述格式来引用静态数据成员;

静态数据成员主要用在各个对象都有相同的某项属性的时候。比如对一个存款类,每个实例的利息都是相同的,所以把利息可以设为存款类的静态数据成员。这有两个好处,一是不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区的内存,所以节省了存储空间。二是一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了。

同全局变量相比,使用静态数据成员有两个优势:

(1)静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性;

(2)可以实现信息隐藏。静态数据成员可以使private成员,而全局变量不能。

2、静态成员函数

与静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务,而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都是在类的内部实现,属于类定义的一部分。普通的成员函数一般都隐藏了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this指针是缺省的、但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针,从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。

Example 6

[cpp] view plaincopy
  1. #include <iostream>
  2. using namespace std;
  3. class MyClass
  4. {
  5. public:
  6. MyClass(int a, int b, int c);
  7. static void fun();
  8. private:
  9. int a,b,c;
  10. static int sum;//声明静态数据成员
  11. };
  12. int MyClass::sum = 0;
  13. MyClass::MyClass(int a, int b, int c)
  14. {
  15. this->a = a;
  16. this->b = b;
  17. this->c = c;
  18. sum += a+b+c;
  19. }
  20. void MyClass::fun()
  21. {
  22. cout<<"sum = "<<sum<<endl;
  23. }
  24. void main()
  25. {
  26. MyClass M(1,2,3);
  27. M.fun();
  28. MyClass N(4,5,6);
  29. N.fun();
  30. MyClass::fun();//静态成员函数的访问
  31. }

关于静态成员函数,可以总结以下几点:

(1)出现在类体外的函数不能指定关键字static;

(2)静态成员之间可以互相访问,包括静态成员函数访问静态数据成员和访问静态成员函数;

(3)非静态成员函数可以任意地访问静态成员函数和静态数据成员;

(4)静态成员函数不能访问非静态成员函数和非静态数据成员;

(5)由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比,速度上会有少许的增长;

(6)调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指调用静态成员函数。

static的三种用法,定义静态变量,静态函数,静态代码块!相关推荐

  1. java静态代码块、静态方法、静态变量、构造代码块、普通代码块、成员变量执行顺序

    package smartt.styy.auth.model.voRsp;public class Test {static {String test5="555";//局部变量t ...

  2. ES6 中三种方式定义对象属性

    ES6 中三种方式定义对象属性 重复样本代码让开发者很不爽,代码混乱掩盖了重要业务代码.ES6关注并解决一些重复的代码方式,使代码简洁.逻辑清晰,如数组解构.对象解构.箭头函数等.本文我们主要介绍利用 ...

  3. C语言块级变量:在代码块内部定义的变量

    所谓代码块,就是由{ }包围起来的代码.代码块在C语言中随处可见,例如函数体.选择结构.循环结构等.不包含代码块的C语言程序根本不能运行,即使最简单的C语言程序(上节已经进行了展示)也要包含代码块. ...

  4. Kotlin object的三种用法

    文章目录 Kotlin object的三种用法 概述 object 匿名内部类 object 单例模式 @JvmStatic companion object 伴生对象 工厂模式 Kotlin obj ...

  5. Java中的this关键字(三种用法)

    this关键字的三种用法: 通过this关键字可以明确的访问一个类的成员变量,解决成员变量与局部变量名称冲突问题. 实例: public class Student {//定义四个成员变量String ...

  6. Java中final的三种用法

    在java中final的三种用法: 1. final成员变量 2. final函数 3. final类 final成员变量 当你在类中定义变量时,在其前面加上final关键字,那便是说这个变量一旦被初 ...

  7. shell子串截取的三种用法:

    使用Shell完成各种Linux运维任务时,一旦涉及到判断.条件测试等相关操作时,往往需要对相关的命令输出进行过滤,提取出符合要求的字符串. 子串截取的三种用法: ${var:起始位置:长度} exp ...

  8. java里break的使用方法_Java中break的第三种用法说明

    在Java中,break语句有三种用法,第一种是用于终止switch语句中的语句序列,第二种是用于退出循环,然而第三种是用作goto语句的"文明"形式! 我们知道,goto语句会破 ...

  9. C++中virtual的三种用法

    virtual用法一 #include using namespace std; class A{ public:virtual void display(){ cout<<"A ...

最新文章

  1. 学习笔记:数据分析和处理(ML计算模型前的预处理)——持续更新
  2. 数据资源 | ​社会科学数据资源
  3. Tkinter的OptionMenu组件
  4. 八十四、Python | Leetcode回溯算法系列
  5. Windows Azure Storage (10) Windows Azure 上的托管服务CDN (下) Hosted Service
  6. mysql group 分页_【MySQL】条件查询之排序聚合分组分页查询
  7. Go语言在扫码支付系统中的成功实践
  8. Java 13:文本块
  9. 中resource文件夹的作用_冲突与碰撞:OpenStack中的虚拟机和裸机
  10. phpstorm 不能自动打开上次的历史文件
  11. 同一个电脑可安装多个python版本吗_Linux下如何安装多个Python版本
  12. 线程休眠 sleep
  13. NET在后置代码中输入JS提示语句(背景不会变白)
  14. java ee 三层架构_JavaEE的三层架构
  15. abbot_release
  16. PySide使用QVariant
  17. 1.2.3 数据模型的组成要素
  18. 【Linux】三、Linux 环境基础及开发工具使用(上篇)|开发工具|编辑器-vim使用|sudo提升权限问题|编译器 - gcc/g++使用|项目自动化构建工构建工具-make/Makefile
  19. XSS插入绕过一些方式总结
  20. 维特比算法的简单实现

热门文章

  1. Ubuntu终端多窗口分屏Terminator
  2. Python开发【第三篇】:Python基本数据类型
  3. 2017-2018-1 20155230 《信息安全系统设计基础》第二周课堂实验
  4. linux系统命令基础知识
  5. 第1次作业+105032014074
  6. Django1.10文档学习笔记二
  7. Fedora安装Texlive2013时出现Can't locate Digest/MD5.pm的解决方法
  8. Angular学习记录一
  9. 汇编语言随笔(5)-and、or指令,串传送指令movsb、访问内存单元的方式及实验4,5(向内存传送数据)
  10. MySQL 报错 1055