本文为个人学习笔记,参考《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用法的更多相关文章

  1. c/c++中static用法总结

    static的作用主要有两种: 第一个作用是限定作用域:第二个作用是保持变量内容持久化: c语言中static的用法: 1.全局静态变量: 用法:在全局变量前加上关键字static,全局变量就定义成一 ...

  2. C++中static用法总结

    1用于局部变量 C++中局部变量有三种: (1)auto:此关键词常常省略.auto type a 常常简写为type a. 如: int a=auto int a 存储在内存的栈中,只在此局部区域有 ...

  3. C/C++中static关键字的用法

    1.什么是static? static 是C/C++中很常用的修饰符,它被用来控制变量的存储方式和可见性. 1.1static的引入 我们知道在函数内部定义的变量,当程序执行到它的定义处时,编译器为它 ...

  4. C/C++中static的用法全局变量与局部变量

    1.什么是static? static 是C/C++中很常用的修饰符,它被用来控制变量的存储方式和可见性. 1.1static的引入 我们知道在函数内部定义的变量,当程序执行到它的定义处时,编译器为它 ...

  5. C++ 中 static 与 const 的用法及对比

    在这个学习过程中我对 static 及 const 的使用时常会混淆,因此整理,加深记忆 一.类的静态成员 如果某个属性为整个类所共有,不属于任何一个具体对象,则采用 static 关键字来声明静态成 ...

  6. Java中static的用法,初始化块

    使用 Arrays 类操作 Java 中的数组语法: Arrays.sort(数组名); 可以使用 sort( ) 方法实现对数组的排序,只要将数组名放在 sort( ) 方法的括号中,就可以完成对该 ...

  7. C++和Java中的静态Static用法

    C++和Java中都有的一个静态关键字Static,可以放在类中的变量或者函数之前,就成了静态变量或者静态函数. 静态变量又分为静态全局变量和静态局部变量,可参见网上大神总结的C++全局变量,局部变量 ...

  8. Java类中static的用法

    关于Java中static的使用有以下四种情况: 1.静态成员变量         被static修饰的成员变量,叫静态成员变量或类变量:没有被static修饰的变量,叫实例变量. 两者的区别是:  ...

  9. C++中static数据成员详解

        本文和大家分享的主要是c++中static数据成员的相关用法及源码示例,希望能帮助大家更好的学习C++. static(静态存储)数据成员 StaticTest.cpp : 定义控制台应用程序 ...

随机推荐

  1. connect by 语句

    create table tb_menu( id number(10) not null, --主键id titlevarchar2(50), --标题 parent number(10) --par ...

  2. 【转】Oracle 如何找回已经删除了的表记录

    有的时候我们不小心把数据库表(emp)中重要的记录给删除了,怎么给找回来了,看下面这个例子你就会明白. 某一天,10点钟的时候,张三一不小心给数据库表emp的一条重要记录给删除了并且还提交了,此时也没 ...

  3. MySQL☞abs函数

    abs( )函数:求出绝对值 格式: select  abs(数值)  from 表名 如下图:

  4. 配置vConsole调试console

    1.使用 npm 安装: npm install vconsole 再使用webpack,然后js代码中 import VConsole from 'vconsole/dist/vconsole.mi ...

  5. leetcode-零钱兑换—int溢出

     零钱兑换 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成总金额,返回 -1. 示例 1: 输入: c ...

  6. Learning Spatial-Temporal Regularized Correlation Filters for Visual Tracking---随笔

    Learning Spatial-Temporal Regularized Correlation Filters for Visual Tracking DCF跟踪算法因边界效应,鲁棒性较差.SRD ...

  7. MyBatis 插件 : 打印 SQL 及其执行时间

    Plugins 摘一段来自MyBatis官方文档的文字. MyBatis允许你在某一点拦截已映射语句执行的调用.默认情况下,MyBatis允许使用插件来拦截方法调用: Executor(update. ...

  8. Eclipse安装颜色主题,个性化你的IDE,让你的IDE焕然一新

    我们都知道eclipse默认的颜色主题是白色的背景,但是如果想改变代码编辑区的背景颜色,需要怎么办呢? 今天给大家介绍一个非常赞的eclipse,可以很方便的根据自己的需求选择喜欢的颜色主题,其他的不 ...

  9. “Hello world!”团队第一周贡献分分配结果

    小组名称:Hello World! 项目名称:空天猎 组长:陈建宇 成员:刘成志.阚博文.刘淑霞.黄泽宇.方铭.贾男男 第一周贡献分分配结果   基础分 会议分 提功能分 个人表现分 各项总分 最终分 ...

  10. Tomcat服务器学习和使用(一)

    一.Tomcat服务器端口的配置 Tomcat的所有配置都放在conf文件夹之中,里面的server.xml文件是配置的核心文件. 如果想修改Tomcat服务器的启动端口,则可以在server.xml ...