「C++系列」C++ 修饰符类型

文章目录

  • 一、C++ 修饰符类型
    • 1. 访问修饰符(Access Modifiers)
    • 2. 存储类修饰符(Storage Class Specifiers)
    • 3. 类型修饰符(Type Modifiers)
    • 4. 函数修饰符
  • 二、C++ 修饰符类型-案例
    • 1. 访问修饰符案例
    • 2. 存储类修饰符案例
    • 3. 类型修饰符案例
    • 4. 函数修饰符案例
  • 三、C++ 中的类型限定符
    • 1. `const` 限定符
    • 2. `volatile` 限定符
  • 四、相关链接

在这里插入图片描述

一、C++ 修饰符类型

在C++中,修饰符(Modifiers)用于改变变量、函数、类成员等的默认行为或属性。这些修饰符可以分为几个主要的类别,包括访问修饰符(Access Modifiers)、存储类修饰符(Storage Class Specifiers)、类型修饰符(Type Modifiers)以及函数修饰符(如constnoexcept用于函数)。下面是对这些修饰符类型的一些简要说明:

1. 访问修饰符(Access Modifiers)

访问修饰符控制类成员的访问权限。

  • public:类外部可以访问。
  • protected:只能被其派生类以及该类的成员访问。
  • private:只能被该类内部的成员函数、友元函数以及类本身访问。

2. 存储类修饰符(Storage Class Specifiers)

存储类修饰符决定了变量/函数的存储方式和作用域。

  • auto:自动变量(局部变量),但现代C++中auto关键字有了新的用途,即自动类型推导。
  • register:建议编译器尽可能将变量存储在寄存器中(但现在很多编译器都忽略了这个建议)。
  • static
    • 对于局部变量,static延长了变量的生命周期,但变量的作用域不变。
    • 对于全局变量和函数,static限制了它们的链接性(linkage),使得它们只在定义它们的文件内可见。
    • 对于类成员变量,static使得变量成为所有对象的共享变量。
  • extern:声明变量或函数是在别的文件中定义的,或者是全局的。
  • thread_local(C++11):声明变量的生命周期与线程相同,每个线程都拥有该变量的一个独立实例。

3. 类型修饰符(Type Modifiers)

类型修饰符影响变量或函数的类型或特性。

  • const:表示变量或函数的返回值不可修改。
  • volatile:告诉编译器该变量的值可能会在程序的控制之外被改变(例如,被操作系统、硬件或其他线程改变)。
  • signedunsigned:用于整数类型,指定变量是有符号还是无符号的。
  • longshort:用于整数类型,指定变量的存储大小。
  • enum:定义枚举类型。
  • structclass:定义复合数据类型。

4. 函数修饰符

  • const:用于成员函数,表示该函数不会修改对象的任何成员变量(如果是非静态成员函数)。
  • noexcept(C++11):指定函数不会抛出任何异常。如果函数确实抛出了异常,程序会调用std::terminate()立即终止。
  • virtual:允许在派生类中重写基类的成员函数。
  • override(C++11):明确指定一个成员函数是重写了基类中的虚函数。
  • final(C++11):用于类和方法,防止类被继承或方法被进一步重写。

二、C++ 修饰符类型-案例

当然,下面我将提供几个使用不同C++修饰符的案例代码。这些案例将涵盖访问修饰符、存储类修饰符、类型修饰符以及函数修饰符。

1. 访问修饰符案例

class MyClass {
public:void publicFunction() {// 公有成员函数,可以在类外部访问}protected:void protectedFunction() {// 保护成员函数,只能在类内部、派生类以及友元中访问}private:void privateFunction() {// 私有成员函数,只能在类内部访问}
};

2. 存储类修饰符案例

#include <iostream>class MyClass {
public:static int staticVar; // 静态成员变量,所有对象共享void printStaticVar() {std::cout << staticVar << std::endl;}
};int MyClass::staticVar = 0; // 静态成员变量的定义int main() {MyClass obj1, obj2;obj1.staticVar = 10; // 通过任一对象修改obj2.printStaticVar(); // 输出 10extern int globalVar; // 声明外部变量// 假设 globalVar 在其他地方定义并初始化// register 修饰符在现代C++中通常不推荐使用,因为它对编译器来说是建议性的// register int regVar; // 示例,但通常不推荐这样做return 0;
}// 假设在另一个文件中定义的 globalVar
// int globalVar = 20;

3. 类型修饰符案例

#include <iostream>class MyClass {
public:void display() const { // const 成员函数,保证不修改任何成员变量std::cout << "Display function called" << std::endl;}// 使用 signed 和 unsignedvoid showIntegers() {signed int sInt = -10;unsigned int uInt = 10;std::cout << "Signed: " << sInt << ", Unsigned: " << uInt << std::endl;}
};int main() {MyClass obj;obj.display();obj.showIntegers();return 0;
}

4. 函数修饰符案例

#include <iostream>
#include <stdexcept>class MyClass {
public:virtual void virtualFunction() {// 虚函数,可以在派生类中被重写std::cout << "Base class function" << std::endl;}void myFunction() noexcept {// noexcept 函数,保证不抛出异常// 如果尝试抛出异常,程序将调用 std::terminate()// 注意:这里的函数体没有实际抛出异常}void overriddenFunction() override { // 使用 override 明确指定重写// 这里是重写基类中的虚函数(假设基类中有相应的虚函数声明)std::cout << "Overridden function" << std::endl;}// 注意:final 修饰符用于类和方法时,表示该类不能被继承或该方法不能在派生类中被重写// 这里没有直接展示 final 的用法,因为它需要在类的继承关系中体现
};// 假设有 MyClass 的派生类,可以展示 virtual 和 override 的用法
// class DerivedClass : public MyClass {
// public:
//     void virtualFunction() override {
//         // 重写 MyClass 中的 virtualFunction
//         std::cout << "Derived class function" << std::endl;
//     }
// };int main() {MyClass obj;obj.virtualFunction(); // 调用基类函数obj.myFunction(); // 调用 noexcept 函数// obj.overriddenFunction(); // 如果 MyClass 中有对应的虚函数声明,则可以这样调用// 演示 noexcept 的异常处理(尽管这个例子没有实际抛出异常)// try {//     throw std::runtime_error("Error");//     obj.myFunction(); // 假设 myFunction 内部有抛出异常的代码,但由于 noexcept,这里不会执行// } catch (...) {//     std::cout << "Exception caught, but myFunction() is noexcept and should not have thrown" << std::endl;//     // 注意:如果 myFunction 实际上是 noexcept 的,并且抛出了异常,程序将不会进入这个 catch 块//     // 相反,它将调用 std::terminate()// }
}

三、C++ 中的类型限定符

在C++中,类型限定符(Type Qualifiers)主要用于限制或改变变量的类型或行为。最常见的类型限定符包括constvolatile。这些限定符可以与基本数据类型、指针、引用等一起使用,以提供额外的信息给编译器和开发者。

1. const 限定符

const限定符用于声明一个变量为常量,意味着一旦该变量被初始化后,其值就不能被改变。const也可以用于修饰函数参数、返回值以及成员函数,以表明这些函数不会(或不应该)修改任何数据。

案例代码

#include <iostream>void display(const int& value) {// 尝试修改value会导致编译错误// value = 10; // 编译错误std::cout << "Value: " << value << std::endl;
}int main() {const int a = 5; // a是一个常量,其值不能被修改// a = 10; // 编译错误display(a); // 传递a的引用,但由于是const,所以display函数内部不能修改它const int* ptr = &a; // ptr是一个指向常量的指针,不能通过ptr修改a的值// *ptr = 10; // 编译错误// 但是,ptr本身是可以被修改的,指向另一个常量const int b = 20;ptr = &b; // 合法,ptr现在指向b// 指向常量的指针的常量(即,指针本身也是常量)int c = 30;const int* const cPtr = &c; // cPtr不能指向其他地址,也不能通过cPtr修改c的值// cPtr = &a; // 编译错误,cPtr是常量return 0;
}

2. volatile 限定符

volatile限定符告诉编译器该变量的值可能会以编译器无法预见的方式被改变。这通常用于嵌入式编程、多线程编程或访问由硬件直接修改的内存位置时。编译器在优化代码时会考虑变量的volatile属性,以确保每次访问该变量时都直接从其内存地址读取值,而不是使用可能已存储在寄存器中的缓存值。

案例代码:(这个案例可能不那么直观,因为它依赖于外部条件来改变变量的值)

#include <iostream>// 假设有一个硬件寄存器,其值可能会被外部事件(如中断)改变
volatile int hardwareRegister = 0; // 声明为volatile,因为值可能随时改变void checkHardwareStatus() {// 循环检查hardwareRegister的值,直到它变为非零(表示某种硬件事件)while (hardwareRegister == 0) {// 在这里,编译器不会优化掉对hardwareRegister的访问// 即使它看起来像是在一个无限循环中}// 处理硬件事件...std::cout << "Hardware event detected!" << std::endl;
}int main() {// 在实际应用中,hardwareRegister的值可能由中断服务例程(ISR)改变// 这里我们模拟这个行为// ...(模拟代码省略)checkHardwareStatus();return 0;
}

volatile的使用应谨慎,因为它会阻止编译器进行某些优化,这可能会降低程序的性能。只有当确实需要时才应使用volatile

四、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C++系列」C++简介、应用领域
  4. 「C++系列」C++ 基本语法
  5. 「C++系列」C++ 数据类型
  6. 「C++系列」C++ 变量类型
  7. 「C++系列」C++ 变量作用域
  8. 「C++系列」C++ 常量知识点-细致讲解

在这里插入图片描述

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

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

相关文章

精讲:java之多维数组的使用

一、多维数组简介 1.为什么需要二维数组 我们看下面这个例子&#xff1f;“ 某公司2022年全年各个月份的销售额进行登记。按月份存储&#xff0c;可以使用一维数组。如果改写为按季度为单位存储怎么办呢&#xff1f; 或许现在学习了一维数组的你只能申请四个一维数组去存储每…

【福利】代码公开!咸鱼之王自动答题脚本

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 微信或QQ打开咸鱼之王小程序&#xff0c;进入答题界面&#xff0c;运行main.py。期间不要动鼠标。 可自行更改代码来适配自己的需求~ 可以按照示例图片…

深入了解线程锁的使用及锁的本质

文章目录 线程锁的本质局部锁的使用 锁的封装及演示线程饥饿问题 线程加锁本质可重入和线程安全死锁问题 根据前面内容的概述, 上述我们已经知道了在linux下关于线程封装和线程互斥,锁的相关的概念, 下面就来介绍一下关于线程锁的一些其他概念. 线程锁的本质 当这个锁是全局的…

Codeforces Round #956 (Div. 2) and ByteRace 2024

A. Array Divisibility 思路: 找出特例,发现输出 1∼&#x1d45b; 符合题意。直接输出1~n即可. 代码: #include<bits/stdc.h> using namespace std; typedef long long ll; #define N 1000005 ll dp[N], w[N], v[N], h[N]; ll dis[1005][1005]; ll a, b, c, n, m, t;…

iOS 开发技巧 - 使用本地 json 文件

前言 使用本地 json 文件的场景&#xff0c;在我们开发功能的阶段&#xff0c;服务端接口字段定义好了后&#xff0c;有些接口响应很慢&#xff0c;请求到响应可能要 几十秒甚至一分钟&#xff0c;我们需要频繁调用接口来调试功能&#xff1b;还有就是调用一些我们需要付费的三…

Ubuntu20.04下修改samba用户密码

Ubuntu20.04下修改samba用户密码 在Ubuntu系统中&#xff0c;修改samba密码通常涉及到两个方面&#xff1a;更改samba用户的密码和重置samba服务的密码数据库。以下是如何进行操作的步骤&#xff1a; 1、更改samba用户密码&#xff1a; 打开终端&#xff0c;使用以下命令更改…

vue打包terser压缩去除控制台打印和断点

情况一&#xff1a; 1、vue-cli搭建 代码压缩工具terser在vue-cli里面是自动支持的&#xff0c;所以直接在vue.config.js里面加入下面配置&#xff1a; const {defineConfig} require(vue/cli-service) module.exportsdefineConfig({transpileDependencies:true,terser:{te…

看影视学英语(假如第一季第一集)

in the hour也代表一小时吗&#xff1f;等同于in an hour&#xff1f;

activemq-CVE-2022-41678

Apache ActiveMQ Jolokia 后台远程代码执行漏洞 Apache ActiveMQ在5.16.5&#xff0c;5.17.3版本及以前&#xff0c;后台Jolokia存在一处任意文件写入导致的远程代码执行漏洞。 启动环境 admin/admin 方法一&#xff1a;利用poc 这个方法受到ActiveMQ版本的限制&#xff0c;因…

Linux 创建新虚拟机的全过程图解

一、创建新虚拟机 1.选择自定义 2.直接下一步 3.选择稍后安装 4.设置虚拟机名和安装位置 5.配置处理器&#xff08;处理器数量&#xff1a;4、每个处理器的内核&#xff1a;2&#xff09; 6. 内存选择 7.网络类型 8. IO控制器类型-默认推荐 9.磁盘类型-默认推荐 10.选择虚拟磁…

JS代码动态打印404页面源码

JS代码动态打印404页面源码&#xff0c;适合做网站错误页&#xff0c;具有js动态打印效果&#xff0c;喜欢的朋友可以拿去 源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务…

Linux udp编程

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

空间计量模型及 Stata 具体操作步骤

目录 一、引言 二、空间计量模型理论原理 空间自回归模型&#xff08;SAR&#xff09;&#xff1a; 空间误差模型&#xff08;SEM&#xff09;&#xff1a;&#xff0c; 空间杜宾模型&#xff08;SDM&#xff09;&#xff1a; 三、实证模型构建 四、数据准备 五、Stata …

14-56 剑和诗人30 - IaC、PaC 和 OaC 在云成功中的作用

介绍 随着各大企业在 2024 年加速采用云计算&#xff0c;基础设施即代码 (IaC)、策略即代码 (PaC) 和优化即代码 (OaC) 已成为成功实现云迁移、IT 现代化和业务转型的关键功能。 让我在云计划的背景下全面了解这些代码功能的当前状态。我们将研究现代云基础设施趋势、IaC、Pa…

【电路笔记】-C类放大器

C类放大器 文章目录 C类放大器1、概述2、C类放大介绍3、C类放大器的功能4、C 类放大器的效率5、C类放大器的应用:倍频器6、总结1、概述 尽管存在差异,但我们在之前有关 A 类、B 类和 AB 类放大器的文章中已经看到,这三类放大器是线性或部分线性的,因为它们在放大过程中再现…

Collection 和 Collections 的区别与用法

Collection 和 Collections 的区别与用法 1、Collection 接口1.1 主要特点1.2 常见方法 2、 Collections 工具类2.1 主要特点2.2 常见方法 3、示例代码3.1 使用 Collection 接口3.2 使用 Collections 工具类 4、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收…

STM32学习历程(day6)

EXTI外部中断使用教程 首先先看下EXTI的框图 看这个框图就能知道要先初始化GPIO外设 那么和前面一样 1、先RCC使能时钟 2、配置GPIO 选择端口为输入模式&#xff0c; 3、配置AFIO&#xff0c;选择我们用的GPIO连接到后面的EXTI 4、配置EXTI&#xff0c;选择边沿触发方式…

LVS实验

LVS实验 nginx1 RS1 192.168.11.137 nginx2 RS2 192.168.11.138 test4 调度器 ens33 192.168.11.135 ens36 12.0.0.1 test2 客户端 12.0.0.10 一、test4 配置两张网卡地址信息 [roottest4 network-scripts]# cat ifcfg-ens33 TYPEEthernet BOOTPROTOstatic DEFROUTEyes DEVIC…

详解平面DP(上)

前言 其实平面DP和正常的dp没有什么本质上的区别&#xff0c;只不过是在二维的面上进行DP&#xff0c;而且&#xff0c;客观的说&#xff0c;其实和递推没有什么区别&#xff0c;不要把他想的太难了 讲解 本蒻鸡思前想后&#xff0c;好像关于平面DP的理论知识好像没有什么&a…

前后端分离系统

前后端分离是一种现代软件架构模式&#xff0c;特别适用于Web应用开发&#xff0c;它强调将用户界面&#xff08;前端&#xff09;与服务器端应用逻辑&#xff08;后端&#xff09;相分离。两者通过API接口进行数据交互。这种架构模式的主要优势在于提高开发效率、维护性和可扩…