const修饰类成员和类对象、const修饰成员函数构成重载、可变数据成员mutable、

2024-03-01 22:08

本文主要是介绍const修饰类成员和类对象、const修饰成员函数构成重载、可变数据成员mutable、,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

其他文章:C++中const成员函数和非const成员函数的重载_梦心之魂的博客-CSDN博客

const修饰数据成员、成员函数

1.const 修饰数据成员:初始化位置可以在参数列表中,新版本也可以在声明位置直接初始化,被const修饰的数据成员,不能被修改

2. const 修饰成员函数:const位置在函数声明之后、实现体之前如果分.h和.cpp的话,要求在定义和声明处都要有const修饰,是从函数的层面,不修改数据。

意义:const函数承诺,不会修改数据成员(无论数据成员有没有const),能访问const 和非const数据成员,但不能修改数据成员,const数据成员只能访问const成员函数因为只有const函数才能保证不会修改
作用:提供对于const对象调用时的支持

#include "stdafx.h"
#include <iostream>
using namespace std;class A
{
public:A(int v = 0):val(v){}//const 只能放在函数后面 因为 const void 和 void const //都是修饰返回类型void的void dis() const{cout << val << endl;//val = 200; const的数据成员一定改不了//x=200; const函数承诺不会修改数据成员(无论加不加const)//print(); 也不可以间接去修改print(); //可以访问const成员函数}void dis(){cout << "void dis() " << endl;}void print()       //this指针的类型是A*{x = 100;y = 200;}void print() const //this指针的类型是const A*{cout << "void print() const" << endl;}
private:const int val; //新版本修饰数据成员可以在这初始化int x, y;
};int _tmain(int argc, _TCHAR* argv[])
{A a(5);        //非const类对象a.dis();       //有非const的成员函数优先 其次调用const成员函数const A a1(5); //const类对象a1.print();a1.dis();      //const对象只能调用const函数return 0;
}

const修饰成员函数与普通成员函数构成重载

在函数重载中有一种特殊的函数重载方法,那就是const修饰成员函数的重载,对于const修饰的类对象,是从对象的层面,不修改数据,只能调用const成员函数。

const对象与const成员函数的调用规则

1.const对象 只能调用const成员函数
2.非const成员对象,优先调用非const成员函数,若没有,则可调用const成员函数

原因:按照函数重载的定义,函数名相同而形参表有本质不同的函数称为重载。在类中,由于隐含的this形参的存在const版本的成员函数使得作为形参的this指针的类型变为指向const对象的指针,而非const版本的使得作为形参的this指针就是正常版本的指针。此处是发生重载的本质。重载函数在最佳匹配过程中,对于const对象调用的就选取const版本的成员函数,而普通的对象调用就选取非const版本的成员函数。(注:this指针是一个const指针地址不能改,但能改变其指向的对象或者变量)

const修饰的成员函数返回类型为*或者&时,最好再使用const来修饰返回值

我们已经知道const修饰成员函数的作用之一就是保证不会修改类中的数据成员,那么如果这个函数将数据成员的*和&类型作为返回值时,我们却可以间接的修改其数据成员,大多情况下,这与我们的期望并不相符,所以在返回类型为引用或指针的const成员函数中,最好再使用const来修改其返回值。

例如String类中我们为它提供一个下标操作符([ ])以读写指定位置的字符,只要了解过C++的操作符重载的语法,很快就可以写出下面这个[]操作符重载函数

char& operator[](int posion)    // function_1{return data[posion];};

注意,这里该函数的返回值为一个引用,否则str[0] = 'c'这样的语句就会不合法,因为str[0]将是一个左值。那么,是否提供这样一个function_1就足够了呢?看下面这段代码:

const String str= "She";
char c = str[0];  // 错误!编译提示:error C2678: 二进制“[” : 没有找到接受“const String”类型的左操作数的运算符(或没有可接受的转换)

很显然,我们必须还要为const String提供一个const版本的opeartor[],因为const修饰的类对象只能调用const修饰的成员函数。

char& operator[](int posion) const
{return data[posion];
}

这样,当使用const的String对象使用[]操作符时,便会调用该const的重载版本。但是,这样就OK了嘛?虽然上面的那段代码没有问题了,但是其中却隐藏了一个陷阱,看如下代码:

const String str = "She";
str[0] = 'T';

上面这段代码可以编译,运行通过,str变为了"The"!而str声明为const的!!现在,你应该知道了,对于const的该操作符重载函数其返回值也应该是const的,否则就会出现可以通过其修改const对象的漏洞。为了给String提供一个[]操作符来读写指定位置的字符,需要提供如下两个函数,以分别对非const String对象和const String对象提供支持

char& operator[](int posion)
{return data[posion];
};const char& operator[](int posion) const
{return data[posion];
}

可变数据成员mutable

有时会发生这样一种情况,我们希望能修改类的某个数据成员,即使是在一个const成员函数内,可以通过在变量的声明加入mutable关键字做到这一点,因此它可以使const成员函数可以改变一个可变成员的值,一个可变数据成员永远不会是const

class Screen
{
public:void some_member() const;
private:mutable size_t access_ctr;  //即使在一个const对象内也能被修改
};void Screen::some_member() const
{++access_ctr;  //保存一个计数值,用于记录成员函数被调用的次数
}

这篇关于const修饰类成员和类对象、const修饰成员函数构成重载、可变数据成员mutable、的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/763980

相关文章

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

MyBatisPlus如何优化千万级数据的CRUD

《MyBatisPlus如何优化千万级数据的CRUD》最近负责的一个项目,数据库表量级破千万,每次执行CRUD都像走钢丝,稍有不慎就引起数据库报警,本文就结合这个项目的实战经验,聊聊MyBatisPl... 目录背景一、MyBATis Plus 简介二、千万级数据的挑战三、优化 CRUD 的关键策略1. 查

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文

mysql中的数据目录用法及说明

《mysql中的数据目录用法及说明》:本文主要介绍mysql中的数据目录用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、版本3、数据目录4、总结1、背景安装mysql之后,在安装目录下会有一个data目录,我们创建的数据库、创建的表、插入的

MySQL 中 ROW_NUMBER() 函数最佳实践

《MySQL中ROW_NUMBER()函数最佳实践》MySQL中ROW_NUMBER()函数,作为窗口函数为每行分配唯一连续序号,区别于RANK()和DENSE_RANK(),特别适合分页、去重... 目录mysql 中 ROW_NUMBER() 函数详解一、基础语法二、核心特点三、典型应用场景1. 数据分

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

Navicat数据表的数据添加,删除及使用sql完成数据的添加过程

《Navicat数据表的数据添加,删除及使用sql完成数据的添加过程》:本文主要介绍Navicat数据表的数据添加,删除及使用sql完成数据的添加过程,具有很好的参考价值,希望对大家有所帮助,如有... 目录Navicat数据表数据添加,删除及使用sql完成数据添加选中操作的表则出现如下界面,查看左下角从左

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编

python 常见数学公式函数使用详解(最新推荐)

《python常见数学公式函数使用详解(最新推荐)》文章介绍了Python的数学计算工具,涵盖内置函数、math/cmath标准库及numpy/scipy/sympy第三方库,支持从基础算术到复杂数... 目录python 数学公式与函数大全1. 基本数学运算1.1 算术运算1.2 分数与小数2. 数学函数

SpringBoot中4种数据水平分片策略

《SpringBoot中4种数据水平分片策略》数据水平分片作为一种水平扩展策略,通过将数据分散到多个物理节点上,有效解决了存储容量和性能瓶颈问题,下面小编就来和大家分享4种数据分片策略吧... 目录一、前言二、哈希分片2.1 原理2.2 SpringBoot实现2.3 优缺点分析2.4 适用场景三、范围分片