C++中static用法
本文为个人学习笔记,参考《C++ Primer(中文第五版)》和《王道程序员求职宝典》
本文分为两个部分:不考虑类、类中static的作用
一、不考虑类,static的作用
1、对其他文件隐藏
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都有全局可见性。同时编译两个源文件:a.cpp和main.cpp,在a.cpp中有以下内容:
#include<cstdio> char a='A'; //全局变量
void msg() printf("Hello\n");
则在a.cpp中定义的全局变量a和函数msg能在main.cpp中使用。这是因为未加static前缀的全局变量都具有全局可见性,其他源文件也能访问。若加了static,就会对其他源文件隐藏了。如在a和msg的定义前加上static,main.cpp就不能访问了。
这样可以在不同的文件中定义同名函数和同名变量,而不用担心命名冲突。
2、static的第二作用是默认初始化为0。
包括未初始化的全局静态变量和局部静态变量。另外未初始化的全局变量也具备之一属性,因为为初始化的全局变量与未初始化的静态变量存储在同一区域内(BSS,全局(静态)存储区,BSS的特点是在程序执行之前BSS会自动清0)。
3、static的第三个作用是保持局部变量内容的持久。
函数内的局部变量,当调用时就存在,退出函数时就销毁,但静态局部变量虽然在函数内定义,但静态局部变量始终存在,也就是说它的生存期为整个源程序,其特点是只进行一次初始化且具有“记忆性”。
值得注意的是:虽然局部静态变量的生存周期为整个源程序,但其作用域仍与局部变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后,尽管该变量嗨继续存在,但不能使用它了。
#include<iostream>
#include<cstddef> using namespace std; size_t count_call()
{
static size_t ctr = ;
return ++ctr;
} int main()
{
for (size_t i = ; i != ; ++i)
{
cout << count_call() << " ";
}
/*未加下一行之前输出1到10,加了之后显示出错:未声明的标识符ctr*/
//cout << ctr << endl; return ;
}
二、类中static的作用
有时候类需要它的一些成员与类本身直接相关,而不是与类的各个对象保持关联,我们可以通过在成员的声明之前加上关键字static使得其与类关联在一起。即,表示属于一个类而不是属于此类的任何特定对象的变量和函数。
类的静态成员存在任何对象之外,对象中不包含任何与静态成员函数有关的数据。和其他成员一样,静态成员可以是public的或private的。什么意思了?下面结合例子我们分静态数据成员和静态成员函数来说
class Account
{
public:
void calculate() {amount+=amount*interestRate;}
static double rate() {return interestRate;}
static void rate(double);
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();
}
1、静态数据成员
通常,非static数据成员存在与类类型的每个对象中,而static数据成员独立与该类的任意对象而存在,即每个static数据成员是与类关联的对象,并不是与该类的对象相关联,通俗讲,静态数据成员不属于类的任一对象。也就是说,当某个类的实例修改了该静态成员变量,其修改值为该类的其他所有实例所见。
(1)静态数据成员定义
因为静态数据成员不属于类的任一对象,所以它们并不是创建类对象时被定义,这意味着不是有类的构造函数初始化。一般来说,static数据成员要在类定义体的外部定义,和其他对象一样,一个静态数据成员只能定义一次。另外,静态数据成语定义在任何函数之外,因为一旦它被定义,就将一直存在于程序的整个生命周期。通俗点讲,对静态数据成员就是不能在类中定义,要类似全局变量一样,单独定义。(有一种例外,见下)
/*定义并初始化一个静态成员*/
double Account::interestTrate=initRate();
(2)静态成员的类中初始化
通常情况下,类的static成员(数据和函数)不应该在类的内部初始化,然而我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的constexpr。
Tip:要想确保对象只定义一次,最好的办法是吧静态数据成员的定义与其他非内联函数的定义放在同一个文件中。
2、静态成员函数
因为普通的成员函数总是具体的属于某个类的具体对象,所以普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身。但是静态成员函数由于不予任何的对象相关联,因此它不具有this指针。因而无法访问类对象的非静态成员函数,也无法访问静态成员函数,只能调用其余的静态成员函数与访问静态数据成员。另外,因为static成员不是任何对象的组成部分,所以static成员函数不能被声明为const。
(1)静态类成员函数既可以定义在类的内部可以在内的外部,当定义在类的外部是,不能重复使用static关键字,该关键字只能出现在类内部的声明语句中。
void Account::rate(double newRate)
{
interestRate=newRate;
}
另外,static成员函数也不能被声明为虚函数、volatile。
(2)静态成员函数可以总结为:
a)静态成员之间可以相互访问,包括静态成员函数访问静态数据和访问静态数据函数。静态成员函数不能访问非静态成员函数和非静态数据成员,非静态成员函数可以任意地访问静态成员函数和静态数据成员。
b)由于没有this指针额外开销,因此静态成员函数与类的非静态成员函数相比速度上会有少许增加。
三、静态成员和普通成员对比
静态成员和普通成员的一个区别是,我们可以使用静态成员作为默认实参:
class Screen
{
public:
/*bkground表示一个在类中稍后定义的静态成员*/
Screen &clean(char=bkground);
private:
static const char bkground;
};
非静态数据成员不能作为默认实参,因为它的值本身属于对象的一部分。
C++中static用法的更多相关文章
- c/c++中static用法总结
static的作用主要有两种: 第一个作用是限定作用域:第二个作用是保持变量内容持久化: c语言中static的用法: 1.全局静态变量: 用法:在全局变量前加上关键字static,全局变量就定义成一 ...
- C++中static用法总结
1用于局部变量 C++中局部变量有三种: (1)auto:此关键词常常省略.auto type a 常常简写为type a. 如: int a=auto int a 存储在内存的栈中,只在此局部区域有 ...
- C/C++中static关键字的用法
1.什么是static? static 是C/C++中很常用的修饰符,它被用来控制变量的存储方式和可见性. 1.1static的引入 我们知道在函数内部定义的变量,当程序执行到它的定义处时,编译器为它 ...
- C/C++中static的用法全局变量与局部变量
1.什么是static? static 是C/C++中很常用的修饰符,它被用来控制变量的存储方式和可见性. 1.1static的引入 我们知道在函数内部定义的变量,当程序执行到它的定义处时,编译器为它 ...
- C++ 中 static 与 const 的用法及对比
在这个学习过程中我对 static 及 const 的使用时常会混淆,因此整理,加深记忆 一.类的静态成员 如果某个属性为整个类所共有,不属于任何一个具体对象,则采用 static 关键字来声明静态成 ...
- Java中static的用法,初始化块
使用 Arrays 类操作 Java 中的数组语法: Arrays.sort(数组名); 可以使用 sort( ) 方法实现对数组的排序,只要将数组名放在 sort( ) 方法的括号中,就可以完成对该 ...
- C++和Java中的静态Static用法
C++和Java中都有的一个静态关键字Static,可以放在类中的变量或者函数之前,就成了静态变量或者静态函数. 静态变量又分为静态全局变量和静态局部变量,可参见网上大神总结的C++全局变量,局部变量 ...
- Java类中static的用法
关于Java中static的使用有以下四种情况: 1.静态成员变量 被static修饰的成员变量,叫静态成员变量或类变量:没有被static修饰的变量,叫实例变量. 两者的区别是: ...
- C++中static数据成员详解
本文和大家分享的主要是c++中static数据成员的相关用法及源码示例,希望能帮助大家更好的学习C++. static(静态存储)数据成员 StaticTest.cpp : 定义控制台应用程序 ...
随机推荐
- hdu1969Pie(根据体积二分,分馅饼)
Pie Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- hdu2553N皇后问题(dfs,八皇后)
N皇后问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- Kotlin的密封(Sealed)类:超强的枚举(KAD 28)
作者:Antonio Leiva 时间:Jun 27, 2017 原文链接:https://antonioleiva.com/sealed-classes-kotlin/ Kotlin的封装类是Jav ...
- loadrunner_遇到cookie接口_3种应对方法
方法一:是调用登录接口,在调用登录后的接口 方法二:手动储存cookie,写死cookie 方法一:提前登录收集cookie,写成参数化文件 方法一,案例(就是先登录,再写登录后的接口): 注:use ...
- pymsql报错:UnicodeEncodeError: 'latin-1' codec can't encode characters End,OK!!
UnicodeEncodeError: 'latin-1' codec can't encode characters的做法基本一致,后来发现是因为使用的是mysqldb,照着网上的方法修改配置应该可 ...
- 关闭Tomcat进程 一条语句(必看)
写在开始 MAC系统下进行JAVA研发,经常遇到的一个问题就是杀死异常Tomcat 通常都是用两条指令,先查询出Tomcat占用的进程,再kill掉该进程, 其实有一种联合语句的方式可以一条语句直接关 ...
- HADOOP docker(十):hdfs 结构体系
1.简介2.namenode和datanode3.The File System Namespace 文件系统命名空间4.Data Replication 数据复制5.Replica Placemen ...
- 基础数据类型-dict
字典Dictinary是一种无序可变容器,字典中键与值之间用“:”分隔,而与另一个键值对之间用","分隔,整个字典包含在{}内: dict1 = {key1:value1, key ...
- C中的除法,商和余数的大小、符号如何确定
对于C中的除法,商和余数的大小.符号是如何确定的呢?在C89中,只规定了如果两个数为正整数,那么余数的符号为正,并且商的值是接近真实值的最大整数.比如5 / 2,那么商就是2,余数就是1.但是,C89 ...
- 软件工程第二周PSP