【学习笔记】C++ 中 static 关键字的作用

目录

  • 前言
  • static 作用在变量上
    • static 作用在全局变量上
    • static 作用在局部变量上
    • static 作用在成员变量上
  • static 作用在函数上
    • static 作用在函数上
    • static 作用在成员函数上

前言

在 C/C++ 中,关键字 static 在不同的应用场景下,有不同的作用,这里总结一下,避免在使用时弄混。

我按照以下的逻辑来分类 static 的作用场景

  1. static 作用在变量上
    1. static 作用在全局变量上:限制全局变量在本文件上
    2. static 作用在局部变量上:即使离开变量作用域,也保存变量值,比如用作计数器
    3. static 作用在成员变量上 :对象间共享该变量
  2. static 作用在函数上
    1. static 作用在函数上:函数可见性限制在本文件中(即使函数被声明在头文件,引用该头文件的其他 cpp 文件也无法使用该函数)
    2. static 作用在成员函数

static 作用在变量上

static 作用在全局变量上

对于普通的全局变量来说,同一项目中的其他文件也可访问相同的全局变量,若为了限制全局变量在本文件中,则需要在这个全局变量上加一个 static,这样该变量就只能在本文件可见。

我们先来演示一下,如何在一个文件中使用另一个文件的全局变量。

假设有 a.cppb.cpp,我们在 b 中定义一个全局变量 staticValue,然后在 a 中打印出来。

// b.cpp
// 全局变量
int staticValue = 10;void staticMain() {// ...
}
// a.cpp
#include <iostream>
using namespace std;// 必须通过 extern 关键字在整个项目搜索 staticValue
extern int staticValue;int main()
{cout << "在 a.cpp 中可见:" << staticValue << endl; // 在 a.cpp 中可见:10
}

显然我们成功在 a 文件中使用到了 b 文件内定义的全局变量。

现在,我希望将 staticValue 的全局可见性,限制在 b 文件内,不让其他文件也可以访问,于是我在 b 的 staticValue 前加上 static 关键字

// b.cpp
// 全局变量
static int staticValue = 10;void staticMain() {// ...
}

将代码如上修改后,当我们再次运行时,程序会在链接阶段报错,报错信息如下,根据描述可见在 aobj 文件(汇编后生成的对象文件)里没有解析到 staticValue 这个变量,达到了我们限制全局变量在本文件内的目的
在这里插入图片描述

static 作用在局部变量上

static 作用在局部变量上,即使离开变量作用域,也保存变量值,比如用作计数器。效果如下面的代码所示

可以看到,num 的值是逐渐累加的过程

#include <stdio.h>void count();int main(void)
{int i=0;for (i = 0;i <= 5;i++){count();}return 0;
}
void count()
{/*声明一个静态局部变量*/static int num = 0;num++;printf("%d\n",num); // 1 2 3 4 5 6
}

static 作用在成员变量上

在这种情况下,static 标记的变量可以在多个对象之间共享该变量,在底层上,因为 static 标记的变量并非存在于对象的内存空间,而是存在于数据区中(这涉及到 C 语言的内存布局)。

具体的效果如下面代码所示,我们声明了 3 个学生对象,分别是 zhangsan,lisi 和 wangwu,并在定义他们的时候给他们传入了各自的初始分数,最终求得三个人的总分。

#include <iostream>
using namespace std;class student {
private:static int sumScore;int myScore;
public:student(int m):myScore(m){sumScore += myScore;}int getSumScore() {return sumScore;}
};int student::sumScore = 0; // 静态成员变量必须在类外被初始化int main()
{student zhangsan(10);student lisi(20);student wangwu(30);cout << wangwu.getSumScore() << endl; // 60return 0;
}

关于 static 在修饰成员变量时的注意事项

  1. static 修饰的成员变量属于类,在对象间共享,因此某个对象修改了该变量,对其他对象也是可见的
  2. 静态成员变量的初始化必须要在类外,如上面的代码所示
  3. 静态成员变量的内存分配是发生在类外初始化的时候,而不是类或者对象创建的时候
  4. 静态成员变量可以通过类,也可以通过对象来访问,但必须遵守访问可见性(publicprivateprotected

static 作用在函数上

static 作用在函数上

它起到的效果和 static 作用在全局变量上类似,将函数的可见性限制在本文件内。

这里我们直接举被 static 修饰的函数的例子。

假设在 b.cpp 中我们定义了一个 bMain() 的函数,在 b.h 的头文件中进行声明,在 a.cpp 中引入这个头文件,并调用 bMain(),那么是可以正常调用的。

现在,我们在 b.cpp 中,在 bMain() 前加上一个 static 关键字,那么 a.cpp 就不能在调用了。

// b.cpp
#include <iostream>
using namespace std;static void bMain() {cout << "bMain" << endl;
}
// b.hpp
void bMain();
// a.cpp
#include "b.hpp"int main()
{bMain();return 0;
}

执行上述代码,我们可以看到和 “static 作用在全局变量上” 小节类似的报错问题
在这里插入图片描述

static 作用在成员函数上

静态成员函数具有和静态成员变量类似的性质和作用,一般可以用这种方式来确定类创建了多少个对象

  1. 静态成员函数在对象之间共享,或者说它独立于对象之外
  2. 可以通过对象来调用静态成员函数,也可以通过类名来调用静态成员函数
  3. 静态成员函数可以访问静态成员变量或其他静态成员函数,但不能使用当前对象指针
#include <iostream>
using namespace std;class student {
private:static int sumObj;
public:student() {sumObj += 1;}static int getObjNum() {return sumObj;}
};int student::sumObj = 0; // 静态成员变量必须在类外被初始化int main()
{student zhangsan;student lisi;student wangwu;cout << "student 有几个对象? " << student::getObjNum() << endl; // 3return 0;
}

可以看到,最终我们输出了 3 个对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/101066.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode128. 最长连续序列

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 题解&#…

如何配置远程访问以在外部网络中使用公司内部的OA办公系统——“cpolar内网穿透”

文章目录 前言1. 确认在内网下能够使用IP端口号登录OA办公系统2. 安装cpolar内网穿透3. 创建隧道映射内网OA系统服务端口4. 实现外网访问公司内网OA系统总结 前言 现在大部分公司都会在公司内网搭建使用自己的办公管理系统&#xff0c;如OA、ERP、金蝶等&#xff0c;员工只需要…

企业架构LNMP学习笔记16

基于IP的访问控制&#xff1a; 基于ngx_http_access_module模块&#xff0c;默认可使用。 语法是&#xff1a; deny ip 禁止IP访问 allow ip 允许IP访问 上面是允许的&#xff0c;下面是deny的。 老师建议写在server段中是比较合适的。 基于用户的访问控制&#xff1a; …

【CSS左右上角斜标签】CSS实现左右上角飘带功能,左右上角斜标签(附源码)

文章目录 写在前面涉及知识点实现效果1、实现过程1.1左上角飘带Html代码Css代码效果 1.2右上角飘带Html代码Css代码效果 2、源码分享2.1 百度网盘2.2 123网盘2.3 邮箱留言 总结 写在前面 其实在公司页面开发过程就遇到过&#xff0c;需要在方块右上角展示一个斜的文字或者告警…

简明易懂:Python中的分支与循环

文章目录 前言分支结构if 语句&#xff1a;单一条件判断else语句&#xff1a;提供备选方案elif 语句&#xff1a;多条件判断嵌套的分支结构&#xff1a;复杂条件逻辑 循环结构for循环&#xff1a;遍历序列range()函数与for循环while循环&#xff1a;条件重复循环控制&#xff1…

Python代码雨

系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/article/details/1295031234漂浮爱心https://want…

这可能是最全面的Python入门手册了!

无论是学习任何一门语言&#xff0c;基础知识一定要扎实&#xff0c;基础功非常的重要&#xff0c;找到一个合适的学习方法和资料会让你少走很多弯路&#xff0c; 你的进步速度也会快很多&#xff0c;无论我们学习的目的是什么&#xff0c;不得不说Python真的是一门值得付出时间…

软件兼容性测试怎么做?对软件产品起到什么作用?

软件兼容性测试是一项重要的软件测试活动&#xff0c;它可以确保在不同操作系统、硬件配置和软件环境下&#xff0c;软件能够正常运行&#xff0c;并与其他相关软件和系统进行正确的互动。 一、软件兼容性的测试方法 1、操作系统测试&#xff1a;测试软件在不同操作系统上的兼…

vmware虚拟机(ubuntu)远程开发golang、python环境安装

目录 1. 下载vmware2. 下载ubuntu镜像3. 安装4. 做一些设置4.1 分辨率设置4.2 语言下载4.3 输入法设置4.4 时区设置 5. 直接切换管理员权限6. 网络6.1 看ip6.2 ssh 7. 本地编译器连接远程服务器7.1 创建远程部署的配置7.2 文件同步7.3 远程启动项目 8. ubuntu安装golang环境8.1…

linux常用命令及解释大全(二)

目录 前言 一、文件的权限 二、文件的特殊属性 三、打包和压缩文件 四、查看文件内容 五、文本处理 5.1 grep 5.2 sed 5.3 其它 总结 前言 本篇文章接linux常用命令及解释大全&#xff08;一&#xff09;继续介绍了一部分linux常用命令&#xff0c;包括文件的权限&a…

OpenCV(二十三):中值滤波

1.中值滤波的原理 中值滤波&#xff08;Median Filter&#xff09;是一种常用的非线性图像滤波方法&#xff0c;用于去除图像中的椒盐噪声等离群点。它的原理是基于邻域像素值的排序&#xff0c;并将中间值作为当前像素的新值。 2.中值滤波函数 medianBlur() void cv::medianBl…

WordPress(5)在主题中添加文章字数和预计阅读时间

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 样式图一、添加位置二、找到主题文件样式图 提示:以下是本篇文章正文内容,下面案例可供参考 一、添加位置 二、找到主题文件 在主题目录下functions.php文件把下面的代码添加进去: // 文章字数…