【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的内容,发现可用的信息很少,要么长篇 ...
随机推荐
- 20155218 《Java程序设计》实验二(Java面向对象程序设计)实验报告
20155218 <Java程序设计>实验二(Java面向对象程序设计)实验报告 一.实验内容及步骤 (一)单元测试 主要学习安装和使用junit来测试编写的程序,并学习以TDD(Test ...
- 20155330 实验三 敏捷开发与XP实践
20155330 实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 实验步骤 (一)敏捷开发与XP 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程. ...
- struts2官方 中文教程 系列四:Action
先贴个本帖的地址,免得其它网站被爬去了struts2教程 官方系列四:Action 即 http://www.cnblogs.com/linghaoxinpian/p/6905521.html 下载 ...
- CF 1064 D. Labyrinth
D. Labyrinth http://codeforces.com/contest/1064/problem/D 题意: n*m的矩阵,只能往左走l次,往右走r次,上下走无限制,问能走到多少个点. ...
- 一个奇怪的JS函数
今天在分析一个jQuery插件源码的时候,发现了一个奇怪的函数. 这个函数的目的是为数字补零,如传入7,输出07,传入12输出12.由于是对时间补零,只截取后两位. // add leading ze ...
- Charles连接苹果及JSON乱码情况解决
1. Charles的JSON乱码情况解决: 点击Charles界面上的help—SSL proxying—install Charles Root Certificate,将证书安装到[受信任的根 ...
- Spine with Unity Mecanim
前言 最近这两天刚刚接触Spine,研究了一下Unity Mecanim Animator如何控制Spine,在此分享记录一下,如有不当之处,请留言指出,欢迎讨论. Unity & Spine ...
- python爬取淘宝华为手机
import re from selenium import webdriver from selenium.common.exceptions import TimeoutException fro ...
- Ubuntu16.04使用Tarball安装ntp
最近在学习linux,看书上例子(鸟哥的linux私房菜 P674),使用Tarball来安装ntp,出了点问题,提示错误,使用 ./configure 来检测程序时,出现如下提示: 提示少了 ope ...
- Tensorflow、Pytorch、Keras的多GPU使用
Tensorflow.Pytorch.Keras的多GPU的并行操作 方法一 :使用深度学习工具提供的 API指定 1.1 Tesorflow tensroflow指定GPU的多卡并行的时候,也是可以 ...