【C++】C++ static关键字详解
- static的作用
1.隐藏
当我们编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,其他的源文件也能访问。如,我们有源文件source1.cpp定义了一个全局变量i和函数Func
//source1.cpp
int i = ; void Func()
{
printf("Hello World\n");
}
如果在另一个文件main.cpp中是可以引用i和Func的。然而,如果一个文件要使用在其他源文件定义的变量或函数,一定要在此文件件中包含相应变量或函数的声明。其中变量一定要用extern声明,函数的声明加不加extern没有影响。如下所示:
//source1.cpp
extern int i; //变量i的声明
void Func(); //函数的声明 int main()
{
printf("%d\n", i); //使用变量i
Func(); //使用函数Func() return ;
}
如果加上static前缀,就不能像上面的程序一样被其他程序使用。
static int i = ; static void Func()
{
printf("Hello World\n");
}
2. static的第二个作用是默认初始化为0,包括未初始化的全局变量与局部静态变量。其实,未初始化的全局变量也具备这一属性,因为未初始化的全局变量与未初始化的静态变量时存储在同一块区域内(BSS段)
3. static的第三个作用是保持局部变量内容的持久。
函数内自动变量,当调用时就存在,退出函数时就消失,但静态局部变量虽然在函数内定义,但静态局部变量始终存在着,也就是说它的声明期为整个源程序,其特点是只进行一次初始化且拒具有'记忆性'。
静态局部变量的生存期虽然为为整个源程序,但其作用域仍然与局部变量相同,即只能在定义该变量的函数内使用该变量。退出函数后,尽管该变量还继续存在,但不能继续使用它。
- 类中static的作用
静态数据成员:
C++重用了static这个关键字,并赋予了它与前面不同的含义:表示属于一个类而不是属于此类对象的任何特定对象的变量和函数。我们可以使用作用于操作符和类的对象、引用或指针来访问静态成员。
通常,非static数据成员存在于类类型的每个对象中。不管该类产生多少个对象,静态成员变量永远只有一个实例,而且在没有对象实例的情况下已经存在。不像普通的数据成员,static数据成员独立于该类的任意对象而存在;每个static数据成员是与类关联的对象,并不与该类的对象相关联。也就是说当某个类的实例修改了该静态数据成员变变量,其修改值为该类的其他所有实例所见。
静态数据成员和普通数据成员一样遵从public、protected、private访问规则。
可以通过作用域操作符从类直接调用static成员,或者通过对象、引用或指向该类类型对象的指针间接调用。
类的数据成员也存储在全局(静态)存储区。静态数据成员定义时要分配空间,所以不能在类声明中定义。
static数据成员可以声明为任意类型,可以是常量、引用、数组、类类型,等等。
因为静态数据成员不属于类的任何一个对象,所以它们并不是在创建类的对象时被定义。这意味着它们不是由类的构造函数初始化。而一般来说我们不能在类的内部初始化静态成员(再定义体内初始化会出错)。相反的,必须在类的外部定义和初始化每个静态成员。和其他对象一样,要给静态数据成员只能定义一次。类似于全局变量,静态数据成员定义在任何函数之外。因此一旦被定义,就将一直存在于程序的整个生命周期中。
这个规则的一个例外是,只要初始化是一个常量表达式,整形const static数据成员就可以在类的定义体中进行初始化(不是定义)。然而,const static数据成员必须在类的定义体之外进行定义。只不过定义时,不在需要初始化。
保证对象正好定义一次的最好办法,就是将static数据成员的定义放在包含类的非内联成员函数定义的文件中。
double Account::interestRate = initRate();
像使用任意的类成员一样,在类定义体外部引用类的static成员时,必须指定成员在哪个类中定义的。然而,static关键字只能用于类定义体内部的声明中,定义不能标示为static。
类的静态成员即可以被类的静态方法访问,也可以被非静态方法访问。static成员函数:
静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分,它为类服务而不是为某一个类的具体对象服务。
当在类外部定义静态成员时(不论是变量还是函数),不能重复static关键字,该关键字只出现在类内部声明语句中。
因为普通成员函数总是具体的属于某个类的具体对象,所以普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身。
与普通成员函数相比,静态成员函数由于不与任何的对象相关联,因此它不具有this指针。因而它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数与访问静态数据成员。
因为static成员不是任何对象的组成部分,所以static成员函数不能被声明为const。也不能被声明为虚函数、volatile。
静态成员函数不需要必须经由类对象调用,也可以像静态数据成员一样使用类名、指向类对象的指针或引用调用:class A {
public:
static void Func() {
cout<<"Hello World"<<endl;
} static int i;
}; int A::i = ; int main()
{
A a;
A* pa = &a;
A &ra = a; A::Func(); //使用类型调用静态成员函数
a.Func(); //使用对象调用静态成员函数
pa->Func(); //使用对象指针调用静态成员函数
ra.Func(); //使用对象引用调用静态成员函数 cout<<A::i<<endl; //使用类型调用静态数据成员
cout<<a.i<<endl; //使用对象调用静态数据成员
cout<<pa->i<<endl;//使用对象指针调用静态数据成员
cout<<ra.i<<endl; //使用对象引用调用静态成员数据 return ;
}关于静态成员函数,可以总结为一下几点:
1. 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员以及静态成员函数。静态成员函数不能访问非静态成员函数和非静态数据成员,非静态数据成员可以任意地访问静态成员函数和静态数据成员;2. 由于没有this指针的额外开销,因此静态成员函数与类的非静态程彦函数相比速度上会有些许的增长。
使用静态成员变量而不是全局变量有三个优点:
1)静态成员的名字是在类的作用域,因此可以避免与其他类的成员或全局对象名字冲突2)可以实施封装。static成员可以是私有成员,而全局对象不可以。
3)通过阅读程序容易看出static成员是与特定类关联的。这种可见性可清晰地显示程序员的意图。
- 参考资料
1. 《C++ Primer 第五版》7.6
2. 《王道程序员求职宝典》
3. 《深度探索C++对象模型》
【C++】C++ static关键字详解的更多相关文章
- Java Static关键字详解
提起static关键字,相信大家绝对不会陌生,但是,想要完全说明白,猛的一想,发现自己好像又说不太明白... ...比方说,昨天被一个同学问起的时候... ... 当然,不是所有人都像我一样学艺不精的 ...
- C/C++中static关键字详解
静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值. 静态变量或静态函数只有本文件内的代码才能访问它,它的名字在其它文件中不可见.用法1:函数内部声明 ...
- C/C++中static关键字详解-zz
静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值. 静态变量或静态函数只有本文件内的代码才能访问它,它的名字在其它文件中不可见.用法1:函数内部声明 ...
- 【转载】static关键字详解
上一篇博客中,因为一个static关键字没有设置好,导致浪费了大量的时间来寻找程序的错误,归根结底,就是大一的时候c语言没有学好. 现在总算知道了,你现在所学的每一个知识点在不就的以后可能及时你的救命 ...
- Java static 关键字详解
引言 在<Java编程思想>中有这样一段话:static方法就是没有this的方法.在static方法内部不能调用非静态方法,反过来是可以的.而且可以在没有创建任何对象的前提下,仅仅通过类 ...
- Java:final、static关键字 详解+两者结合使用
一 final关键字 1) 关于final的重要知识点 final关键字可以用于成员变量.本地变量.方法以及类. final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误. ...
- java中的static关键字详解
static对于我们这些初学者在编写代码和阅读代码是一个难以理解的关键字,也是大量公司面试题最喜欢考的之一.下面我就来就先讲述一下static关键字的用法和我们初学者容易误解的地方. static关键 ...
- C/C++中的static关键字详解
C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用.一.面向过程设计中的sta ...
- static关键字 详解
原文地址:http://blog.csdn.net/keyeagle/article/details/6708077 google了近三页的关于C语言中static的内容,发现可用的信息很少,要么长篇 ...
随机推荐
- 第十四周 P187教材检查
在IDEA中或命令行中运行P187 Guess.java. 这道题是继承语法抽象类一块的知识点,题目本身其实并不难,但是当时做的时候我找自己原来的代码花了很长时间,刚找到运行完截好图,就到时间了. 当 ...
- 20155319 2016-2017-2 《Java程序设计》第十周学习总结
20155319 2016-2017-2 <Java程序设计>第十周学习总结 教材学习内容总结 计算机网络编程概述 网络编程就是两个或多个设备之间的数据交换,其实更具体的说,网络编程就是两 ...
- 分享daocloud联合创始人陈齐彦关于docker的一段阐述
罗比,本名陈齐彦,他在加入DaoCloud之前是EMC中国研究院的总架构师,云平台及应用实验室的创始人.谈及创业的初心,他激动了起来: 容器这东西和当年Hadoop一样,是互联网技术对企业IT技术的逆 ...
- Mysql优化分页
背景: 库里面有张表,日增数据量百万条: 之前查询: SELECT * FROM `res_battery_data_history` LIMIT 1797000,10;
- P1546 最短网络(codevs | 2627村村通)
P1546 最短网络 Agri-Net 题目背景 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助. 题目描述 约翰已经给他的农场安排了一 ...
- rsync + inotify 数据实时同步
一.rsync介绍 rsync英文全称为Remote synchronization,从软件的名称就可以看出来,Rsync具有可是本地和远程两台主机之间的数据快速复制同步镜像.远程备份的功能,这个功能 ...
- docker error:/root/.docker/config.json: is a directory
问题: 本地没有taskworker镜像,docker从远端拉取,但是拉取时需要读取config.json配置,解析配置时,发现config.json是个目录,错误信息如下: taskworker_1 ...
- PHP反序列化漏洞代码审计—学习资料
1.什么是序列化 A.PHP网站的定义: 所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示.unserialize()函数能够重新把字符串变回php原来的值. ...
- APP端测试,常见功能测试点汇总
除去每个产品和版本不同的业务需求以及功能,针对于大多数的APP的共同点和移动设备的特性,本文总结了一些APP功能测试中经常遇见,需要考虑到的测试点以共参考 一.安装和卸载 应用的安装和卸载在任何一款A ...
- Linux 安装Redis<单机版>(使用Mac远程访问)
阅读本文需要先阅读安装Redis<准备> redis依赖 yum install gcc-c++ 解压 cd redis压缩包所在目录 tar -xvf redis-4.0.10.tar. ...