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

news2024/10/1 5:41:17

文章目录

  • 一、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(); // 输出 10

    extern 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 和 unsigned
    void 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.coloradmin.cn/o/1913103.html

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

相关文章

以终为始,胜意费控云「包干管控」助力精细管控与体验提升

在全球宏观经济环境的波动和内在经济逻辑的推动下&#xff0c;我国经济正经历着关键的结构调整期。如何稳健穿越周期&#xff0c;是企业必须直面的课题。与此同时&#xff0c;企业成本管控也面临着更为精细和严格的挑战。 企业需要一种更为灵活合理的费用管控策略。胜意费控云升…

【人工智能】-- 搜索技术(状态空间法)

个人主页&#xff1a;欢迎来到 Papicatch的博客 课设专栏 &#xff1a;学生成绩管理系统 专业知识专栏&#xff1a; 专业知识 文章目录 &#x1f349;引言 &#x1f348;介绍 &#x1f349;状态空间法 &#x1f348;状态空间的构成 &#x1f34d;状态 &#x1f34d;算符…

Pyecharts绘制热力图的说明+代码实战

引言 热力图在数据可视化中是一种强大的工具&#xff0c;可以直观地展示数据的分布情况和变化趋势。Pyecharts是一个基于Echarts的Python可视化库&#xff0c;提供了丰富的图表类型&#xff0c;包括热力图。在本文中&#xff0c;我们将深入探讨Pyecharts绘制多种炫酷热力图的参…

数据结构 实验 3

题目一&#xff1a;最短路径dijkstra算法 一、实验目的 熟练图的邻接矩阵和邻接表表示法掌握图的最短路径Dijkstra算法的基本思想用C语言实现Dijkstra算法 二、实验内容 从键盘输入的数据创建图&#xff08;图的存储结构采用邻接矩阵&#xff09;&#xff0c;设计Dijkstra算…

领导者视角:识别系统问题的信号

作为企业的领导者&#xff0c;有时候我们面对的不仅是表面的小问题&#xff0c;而是根深蒂固的系统性问题。如果您发现以下症状&#xff0c;可能就是时候深入挖掘了&#xff1a; 1、资源消耗大&#xff1a;一个看似小的问题&#xff0c;解决起来却不断耗费大量资源。 2、反复无…

LeetCode热题100刷题10:46. 全排列、78. 子集、17. 电话号码的字母组合、39. 组合总和、138. 随机链表的复制

回溯问题 46. 全排列 全排列问题&#xff1a; path 递归终止条件&#xff1a;path中是否已存储所有元素&#xff1b; for循环处理节点集合&#xff1a;used0未被使用的元素 class Solution { public:vector<int> path;vector<vector<int>> res;void backt…

odoo中的钩子 Hooks

钩子 钩子&#xff08;Hooks&#xff09;是一种在特定时间点或特定事件发生时执行自定义代码的机制。它们允许开发者在不修改核心代码的情况下&#xff0c;为Odoo添加自定义功能或扩展现有功能。以下是关于Odoo钩子的一些关键点和常见用法&#xff1a; 一、钩子的类型 pre_i…

Thinking--在应用中添加动态水印,且不可删除

Thinking系列&#xff0c;旨在利用10分钟的时间传达一种可落地的编程思想。 水印是一种用于保护版权和识别内容的技术&#xff0c;通常用于图像、视频或文档中。它可以是文本、图像或两者的组合&#xff0c;通常半透明或以某种方式嵌入到内容中&#xff0c;使其不易被移除或篡改…

《Windows API每日一练》9.13资源-鼠标位图和字符串

鼠标指针位图&#xff08;Mouse Cursor Bitmap&#xff09;是用于表示鼠标指针外观的图像。在 Windows 窗口编程中&#xff0c;可以使用自定义的鼠标指针位图来改变鼠标的外观&#xff0c;并提供更加个性化的用户体验。 ■以下是一些与鼠标指针位图相关的要点&#xff1a; ●…

局域网远程共享桌面如何实现

在局域网内实现远程共享桌面&#xff0c;可以通过以下几种方法&#xff1a; 一、使用Windows自带的远程桌面功能&#xff1a; 首先&#xff0c;在需要被控制的电脑上右键点击“此电脑”&#xff0c;选择“属性”。 进入计算机属性界面后&#xff0c;点击“高级系统设置”&am…

这不是在搞技术,而是在玩心态~

正文 大家好&#xff0c;我是bug菌~ 如今为制造业提供大型设备的研发型公司大多数都是做系统集成&#xff0c;一部分有技术实力的公司会把核心部分自研&#xff0c;其他相对比较通用的周边设备由其他公司产品来集成&#xff1b;也有一部分公司只是做做方案和资源整合&#xff0…

科普文:深入理解负载均衡(四层负载均衡、七层负载均衡)

概叙 网络模型&#xff1a;OSI七层模型、TCP/IP四层模型、现实的五层模型 应用层&#xff1a;对软件提供接口以使程序能使用网络服务&#xff0c;如事务处理程序、文件传送协议和网络管理等。&#xff08;HTTP、Telnet、FTP、SMTP&#xff09; 表示层&#xff1a;程序和网络之…

bazel基础知识

ABOUT BAZEL 什么是Bazel&#xff1f; 构建系统&#xff0c;而不是构建生成器&#xff08;直接调用编译器&#xff09;【A build system, not a build generator (invokes directly the compiler)】 具有完整的测试功能&#xff08;测试报告、片状测试处理等&#xff09;【Wi…

腾讯又一平台即将停止运营

随着腾讯公司业务和战略的调整&#xff0c;某些业务逐渐退出历史舞台&#xff0c;如“腾讯直播平台NOW”&#xff0c;以及“QQ签到”&#xff0c;“腾讯待办”&#xff0c;“企鹅FM音频平台”等&#xff0c;最近又有一则重磅消息&#xff0c;那就是“腾讯课堂”也即将停止运营。…

【Linux】进程(9):进程控制2(进程等待)

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解Linux进程&#xff08;9&#xff09;进程控制2&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 一. 为什么要进程等待二. 如何进行进程等待1.wait函数—…

学习嵌入式对于学历有要求吗?

学习嵌入式系统开发通常并不对学历有严格的要求&#xff0c;尤其是在技术行业中&#xff0c;实际的技能和经验往往比学历更为重要。我收集归类了一份嵌入式学习包&#xff0c;对于新手而言简直不要太棒&#xff0c;里面包括了新手各个时期的学习方向编程教学、问题视频讲解、毕…

设计无缝体验:交互设计流程全解析

完整的产品交互设计流程是什么&#xff1f;完整的产品交互设计流程包括研究用户需求、指定信息架构、制作产品原型、进行用户测试和实时发布产品。交互设计就是从人与产品之间的关系入手&#xff0c;通过产品设计来满足大众的日常需求。随着网络技术的流行&#xff0c;产品交互…

高性能Python网络框架实现网络应用详解

概要 Python作为一种广泛使用的编程语言,其简洁易读的语法和强大的生态系统,使得它在Web开发领域占据重要位置。高性能的网络框架是构建高效网络应用的关键因素之一。本文将介绍几个高性能的Python网络框架,详细描述它们的特点、使用场景及具体示例代码,帮助高效实现网络应…

鸿蒙语言基础类库:【@ohos.util.ArrayList (线性容器ArrayList)】

线性容器ArrayList 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 …

windows USB 设备驱动开发-USB带宽

本文讨论如何仔细管理 USB 带宽的指导。 每个 USB 客户端驱动程序都有责任最大程度地减少其使用的 USB 带宽&#xff0c;并尽快将未使用的带宽返回到可用带宽池。 在这里&#xff0c;我们认为USB 2.0 的速度是480Mbps、12Mbps、1.5Mbps&#xff0c;这分别对应高速、全速、低速…