本文为个人学习笔记,参考《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. MAC 更新brew 镜像源

    mac 更新brew镜像源 cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core" git remote set-url o ...

  2. 180612-Spring之Yml配置文件加载问题

    Yml配置文件加载问题 在resource目录下有一个application.yml文件,希望是通过@PropertySource注解,将配置文件数据读取到Environment中,然而调试发现数据始 ...

  3. 爬虫2.1-scrapy框架-两种爬虫对比

    目录 scrapy框架-两种爬虫对比和大概流程 1. 传统spider爬虫 2. crawl型爬虫 3. 循环页面请求 4. scrapy框架爬虫的大致流程 scrapy框架-两种爬虫对比和大概流程 ...

  4. python leveldb 文档

    标签(空格分隔): python leveldb import leveldb db = leveldb.LevelDB('./db') db.Put('hello', 'world') print ...

  5. dice2win

    触发交易 转0个 https://etherscan.io/tx/0x784e80167353a886183106cbe3bd15e614cafdb5d6885ccd101177aa0f937a36 ...

  6. 文件操作---基于python

    # coding:utf-8from time import sleepimport sysreload(sys)sys.setdefaultencoding("utf8")f=o ...

  7. POJ 3845 Fractal(计算几何の旋转缩放)

    Description Fractals are really cool mathematical objects. They have a lot of interesting properties ...

  8. NFC学习总结二

    移动支付这事情热了总归还是会回归理性,就如同之前的10几年间的几次轮回一样.字面上看,移动支付比支付大也不大可能,有相同,有扩展,有交集有不通才是. NFC这事情也是说了快十年了,真心希望它能回归到其 ...

  9. 衡量经济活动的价值:国内生产总值(GDP, Gross Domestic Product)

    定义 GDP是在给定的时期内,经济生产的所有最终产品和服务的市场价值. 由于每一件产品或者服务的交易都会涉及到一个买者和一个卖着,买者支出的每一元钱必然成为卖者收入的每一元钱,因此,GDP既可以看成是 ...

  10. string && 字符数组

    一.string 1. 使用字符串字面值初始化string对象 如:string s1 = "hiya"; string s2("hiya"); 该字面值的最后 ...