深入探索C++类的const成员函数

2023-10-30

深入探索C++类的const成员函数

const 成员变量的用法和普通 const 变量的用法相似,只需要在声明时加上 const 关键字。初始化 const 成员变量只有一种方法,就是通过构造函数的初始化列表。

const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值,这种措施主要还是为了保护数据而设置的。const 成员函数也称为常成员函数。

我们通常将 get 函数设置为常成员函数。读取成员变量的函数的名字通常以get开头,后跟成员变量的名字,所以通常将它们称为 get 函数。

(1)const 成员函数把 const 关键字放在函数的形参列表和函数体之间。比如

class A
{
    void f() const {}
    const int g()
    {
        return 2;
    }
};

其中函数 f 是 const 成员函数,函数 g 只是一个返回类型为 const int 的函数。

(2)在类体外定义 const 成员函数时也必须同时指定 const 关键字。比如

class A
{
    void f() const;
};

在类体外定义函数 f 的形式为

void A::f() const f{...};

(3)在 const 成员函数体内,数据成员相当于被 const 修饰,即 const 成员函数不能修改类的数据成员,但非类的数据成员则可以修改。

比如

class A
{
    int a;
    void f(int b) const
    {
        int c;
        b = l;
        c = 2;
        a = l;
    }
};

其中 a = 1; 是错误的,其他都是正确的。因为 b 和 c 不是类的数据成员。再比如

class A
{
    int a;
    void f() const 
    {
        int* p = &a;
        const int *pl = &a;
    }
};

其中 const int *pl = &a; 是正确的,int* p = &a; 是错误的,因为指向非 const 的指针不能指向 const 常量,在 const 成员函数内部相当于被 const 修饰。

(4)在 const 成员函数体内,成员指针也相当于被 const 修饰,但 const 是修饰的指针本身也就是指针成员相当于 * const p 。因此在

const 成员函数体内能修改指针成员所指向的对象的值但不能改变指针成员本身的值,或者说指针成员是常量,但指向的值不是常量。比如

class A
{
public:
    int a;
    int *p;
    void f() const
    {
        int b = l;
        *p = 3;
        p = &b;
    }
};

其中 p = &b; 是错误的。注意:需要加一个构造函数初始化指针 p。

(5)const 成员函数可以与具有相同参数表的非 const 成员函数形成重载,在调用时,非 const 对象将调用非 const 成员函数,而 const 对象则只能调用 const 成员函数。比如 class A{void f(){}; void f() const{} };,其中的两个函数 f 是重载关系,而非重定义;再比如const A ma; A mb;,则 ma.f() 将调用 const 成员函数,mb.f() 将调用非 const 成员函数。

(6)const 成员函数不能调用非 const 成员函数。因为在const 成员函数内,调用类的成员时需要通过隐藏的 this 指针,而 const 成员函数的 this 指针类型为 const 类名 *const ,即既不能改变 this 指针本身的值,也不能改变 this 指针所指向的对象,因为无法保证非 const 成员函数不改变数据成员的值,所以const成员函数不能调用非 const 成员函数。

(7)注意:若使用强制转换去掉 this 的 const 性质,const 成员函数就可以调用非 const 成员函数了;同理,也可以在 const 成员函数内改变数据成员的值。比如

class A
{
public:
    int a;
    void g() {}
    void f() const
    {
        ((A* const)this)->g();
        ((A* const)this)->a=4;
    }
};

正确,其中 ((A* const)this) 表示把 this 指针强制转换为 A* const ,即强制转换去掉了最前面的 const。

(8)注意:非成员函数不能把 const 关键字放在小括号之后,比如 void f()const{}; 是错误的。

例子

class Student{
public:
    Student(char *name, int age, float score);
    void show();
    //声明常成员函数
    char *getname() const;
    int getage() const;
    float getscore() const;
private:
    char *m_name;
    int m_age;
    float m_score;
};

Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(){
    cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
//定义常成员函数
char * Student::getname() const{
    return m_name;
}
int Student::getage() const{
    return m_age;
}
float Student::getscore() const{
    return m_score;
}

该文章会更新,欢迎大家批评指正。

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
服务器课程:C++服务器

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入探索C++类的const成员函数 的相关文章

  • 插入多重集中:在该值第一次出现之前而不是最后一次出现之后

    正如标题所示 multiset 在所有相同值的范围末尾插入一个值 例如 在多重集中插入 21 2 2 3做到了1 2 2 new 2 3 如何在所有相同值的范围开头插入新值 例如 在多重集中插入 21 2 2 3应该使1 new 2 2 2
  • 为什么纯虚拟析构函数的实现必须为空?它应该是内联的吗?

    我在其他线程中读到 当您实现纯虚拟析构函数 是的 它可以有一个实现 时 它必须是空的 并且应该 是内联的 应该是空的吗 如果是这样 为什么 应该内联吗 如果是这样 为什么 编辑 这就是纯虚拟析构函数的实现方式 class A virtual
  • 使用 C 序列化 double 和 float

    如何在 C 中序列化双精度数和浮点数 我有以下用于序列化短整型 整数和字符的代码 unsigned char serialize char unsigned char buffer char value buffer 0 value ret
  • 从 pdf 和 word 文件中提取文本

    如何在 C 中从 pdf 或 word 文件中提取文本 删除粗体 图像和其他富文本格式媒体 您可以使用专为索引服务设计 由索引服务使用的过滤器 它们旨在从各种文档中提取纯文本 这对于在文档内部进行搜索非常有用 您可以将其用于 Office
  • 如何使用 CMake 链接多个库

    我有一些与 DCMTK 相关的代码 如果我从命令行使用 g 我可以成功构建并运行它 这是代码 include dcmtk config osconfig h include dcmtk dcmdata dctk h int main Dcm
  • 减少最大值并保存其索引

    int v 10 2 9 1 3 5 7 1 2 0 0 int maximo 0 int b 0 int i pragma omp parallel for shared v private i reduction max maximo
  • 值类型数组如何存储在 .NET 对象堆中?

    在 NET中 诸如int之类的值类型对象存储在内存中 引用类型对象需要为引用和对象单独分配内存 并且对象存储在 NET对象堆中 而Array是在堆中创建的 那么int 等值类型的数组如何存储在堆中呢 这是否意味着值类型对象可以存储在堆中而无
  • 如何更改控制台中的光标位置?

    我想用Console ReadLine 在上一行中并使其显示如下 HeresomeText gt input Not like HeresomeText gt input 可以做吗 使用 Write 方法而不是 WriteLine 方法 C
  • gcc 的错误?模板类中友元函数的访问控制问题

    我有一个模板类 并在类中定义了一个友元函数 include
  • C++ 访问嵌套类的私有成员

    标题可能有点误导 我有以下问题 我有一棵由叶子和内部节点组成的树 用户应该能够在叶子中存储任何信息and该树有一些方法可以获取一组用户定义的值 并且需要在恒定时间内 未摊销 访问相应的叶子 我提出了以下想法 但它不起作用 因为不幸的是我无法
  • 在实体框架中不使用 Dispose 或 using()

    我一路上正在编写一个网络应用程序并学习实体框架 如果我做错了什么 我很好奇 我在查询时没有使用过 dispose 或 using 语句 我的存储库示例 public User GetUserById int sessionId var us
  • 在多个线程中添加和删除时 List 中的 null 值

    我知道 C System Collections Generic List 对象不是线程安全的 但我想知道为什么这段代码会生成空值 Task Run gt for var i 0 i lt 10 i var str Test i list
  • WiX 安装程序在 vs 2012 上不起作用

    我想为我的应用程序创建一个安装程序 我已经下载了 WiX 3 6 并将其安装在 vs 2012 上 创建简单的winform应用程序 将 WiX 安装项目添加到我的解决方案中 右键单击参考并将我的 winform 应用程序添加到安装程序的参
  • 是否可以使用 struct stat 描述符获取和设置文件名?

    是否可以在获取或设置 重命名 文件名时给出文件的绝对路径 并将 struct stat 实例作为 lstat 函数的参数 正如我在文档结构中发现的那样 struct stat dev t st dev ID of device contai
  • 在方法签名中使用 new 关键字通常只是为了可读性吗?

    我读过关于new关键词在方法签名中并看到了下面的例子this https stackoverflow com questions 1014295 c sharp new keyword in method signature发帖了 但还是不
  • TPL架构问题

    我目前正在开展一个项目 我们面临并行处理项目的挑战 到目前为止没什么大不了的 现在来说说问题 我们有一个 ID 列表 我们定期 每 2 秒 为每个 ID 调用一个 StoredProcedure 需要单独检查每个项目的 2 秒 因为它们是在
  • 系统.安全.加密与 PCLCrypto

    我们正在删除系统中的许多共享功能并将其移植到 PCL 库中 我在使用 PCLCrypto 时遇到问题 我正在获取数据库中的一些现有数据 并尝试使用相同的算法对其进行解密 我得到了值 但末尾有 16 个额外字节 这些字节都是垃圾 参见下面的代
  • Interlocked.CompareExchange 可以抛出 NullReferenceException 吗?

    From https msdn microsoft com en us library bb297966 v vs 110 aspx https msdn microsoft com en us library bb297966 v vs
  • 如何用纯色填充位图?

    我需要使用唯一的 RGB 颜色创建 24 位位图 分辨率 100x100 像素 并将生成的图像保存到磁盘 我目前使用的是SetPixel http msdn microsoft com en us library 6c7eyzyb aspx
  • 从 C# 调用 C++ DLL

    我想使用 C 中的 C DLL C DLL 是win32 控制台应用程序 我已成功调用它 并希望在 C 中处理来自 C 的数据 然而 C 应用程序在执行 DLL 后退出 即这一行 GetArrayFromDLL 我是 C 和 Visual

随机推荐

  • QTCreator在Ubuntu安装及运行程序报错解决

    1 QT Creator安装 软件包下载 可以进入官网下载或者使用wget命令下载 个人使用wget命令安装如下 sudo wget http download qt io archive qt 5 12 5 12 9 qt opensou
  • VScode修改行间距

    在我们编码的过程中 由于显示字体和显示器的不同 会需要调整行间距 在vscode默认的选项中没有看到设定行间距的选项 不过 可以手动修改配置档达到目的 1 打开设置 2 打开配置档 手动进行设定 3 在选项中添加 editor lineHe
  • Kafka中Producer源码解读

    Producer源码解读 在 Kafka 中 我们把产生消息的一方称为 Producer 即 生产者 它是 Kafka 的核心组件之一 也是消息的来源所在 它的主要功能是将客户端的请求打包封装发送到 kafka 集群的某个 Topic 的某
  • Qt极简贪吃蛇实现

    持续修正更新该项目 环境 Qt 4 8 Qt5环境也可使用 全部文件传送门 部分重要模块代码 include snakegame h include ui snakegame h SnakeGame SnakeGame QWidget pa
  • 连接SQL Server 数据库

    目录 一 启动 SQL Server Management Studio 1 点击 SQL Server Management Studio 菜单进入 2 选择服务器和身份验证方式 3 点击连接进入数据库 二 新建数据库 1 数据库的概念
  • 6370小时时,在公司稳定兼职(4000/月)(2016年5月2日 PS:实际上并不是稳定兼职,没项目了就没钱了。)

    周六时 兼职的公司要去了我的工行卡号 以后每月打4000到我的卡里 我需要调整规划了 2016年5月2日 PS 实际上并不是稳定兼职 没项目了就没钱了
  • Linux C文件IO操作

    文件IO 在Linux中万物都为文件 普通文件 设备 socket 标准输入输出等等 常用接口 Method Parameters Descriptions Return H open char name int flags mode 打开
  • python学习3.1

    一 if 语句的使用 if 后的语句是否执行 也跟缩进有关 1 if else eg 输入 bands oasis the beatles eagles the who the kinks for band in bands if band
  • Alist搭建

    Alist简介 一个支持多种存储的文件列表程序 AList设计易于安装 可以在所有平台上使用 支持多个存储提供商 包括本地存储 阿里云盘 OneDrive Google Drive 等 且易于拓展 支持所有 WebDAV 存储 支持视频 音
  • Python tkinter如何把窗口在屏幕中央居中

    Python tkinter如何把窗口在屏幕中央居中 coding utf 8 import tkinter as tk 创建 Tkinter 窗口 root tk Tk 设置窗口大小 root geometry 400x300 获取屏幕宽
  • 企业微信消息多久可以撤回?企业微信怎么查看撤回的消息?

    大家都知道 个人微信是可以撤回两分钟以内的消息 超过两分钟就无法撤回了 那企业微信可以撤回发送了多久的消息呢 撤回的消息还能够查看吗 跟着企业微信服务商艾客scrm小编 一起来看看吧 其实 我们使用任何一个聊天工具聊天的过程中 撤回消息在所
  • Unity URP渲染管线与内置渲染管线的性能差别

    首先 我们来了解一下Unity的内置渲染管线 内置渲染管线是Unity较早版本中使用的默认渲染管线 它使用的是传统的图形渲染技术 内置渲染管线提供了一系列的渲染功能 如阴影 反射 抗锯齿等 但是 由于其较为庞大且复杂的设计 它的性能相对较低
  • qt动态显示当前时间如何实现

    Qt qt动态显示当前时间如何实现 vestinfo 1 票 182 include mainwindow h include ui mainwindow h include
  • Java面向对象编程

    第一章 类与对象 面向对象简介 面向过程指的是面对于一个问题的解决方案 更多情况下不会做出重用的设计 面向对象主要设计形式为模块化设计 可以进行重用配置 更多情p况下考虑的是标准 然后根据标准进行拼装 面向对象有三个主要特性 封装性 内部的
  • 【目标检测】Mask RCNN的训练数据集是什么?(含labelimg和labelme的讲解)

    文章目录 一 训练数据集 二 标注工具介绍 2 1 labelimg介绍 2 2 labelme介绍 2 3 两者的对比 三 制作数据案例 在看完何凯明大神的Mask RCNN的时候 突然想到了一个问题 那就是Mask RCNN的训练数据集
  • JAVA-使用Thumbnails压缩图片

    使用Thumbnails压缩图片
  • 休息是不可能休息的

    654 最大二叉树 分析 相比较遍历顺序构建二叉树 这个相对简单 思路 每次找到数组最大值 然后分割数组 class Solution public TreeNode judge vector
  • VersionCode和VersionName的区别

    最近在研究Android4 1的新功能 增量升级 判断客户端apk的版本号和服务器端的版本号在清单文件中VersionCode和VersionName的区别 记录一下 方便自己或者用到的朋友查看 先上结论 Google为APK定义了两个关于
  • 视频场景切换检测(镜头边界检测、镜头分割)

    个人简介 深度学习图像领域工作者 总结链接 链接中主要是个人工作的总结 每个链接都是一些常用demo 代码直接复制运行即可 包括 1 工作中常用深度学习脚本 2 torch numpy等常用函数详解 3 opencv 图片 视频等操作 4
  • 深入探索C++类的const成员函数

    深入探索C 类的const成员函数 const 成员变量的用法和普通 const 变量的用法相似 只需要在声明时加上 const 关键字 初始化 const 成员变量只有一种方法 就是通过构造函数的初始化列表 const 成员函数可以使用类