在C++中,可以用const来定义一个const对象,但const对象不可以调用类中的非const成员函数

原因

引发原因:: 由调用成员函数时隐式传入的当前对象的this指针引起。

  1. 非const成员函数中的隐式参数:classA* this
  2. const成员函数中的隐式参数:const classA* this

根本原因:

  1. const对象的指针为const classA* this,因此传入非const成员函数时编译器报错(类型不匹配,无法从const 指针转换为非const指针);但传入const成员函数则类型匹配。
  2. 非const对象的指针为classA* this,可以调用const成员函数,因为const修饰符保证了不会修改该对象。

代码解释

假设有一个类,名字为test代码如下:

class test{public:void print()const;
};

我们知道C++在类的成员函数中还会隐式传入一个指向当前对象的this指针,所以在test类中,实际的print函数应该是这样的void print(test * this);,这代表一个指向test对象的指针this被传入到了print函数中
假如现在我们用test类创建一个对象,

test obj1(12);
obj1.print();

第二句,obj1.print();其实相当于print(&obj1);,即把当前的对象obj1的指针传递到print()函数,这是没问题的

如果用test类创建一个const对象,然后去调用print()函数呢?这就会出现问题

const test obj2(122);
obj2.print();

这时obj2对象的指针就会传递给test *this指针,而obj2的地址翻译成指针类型应该是这样的,const test* this,即这时会出现类型不匹配的错误,在visual studio 中会出现类似于下面的错误:

所以通过上面的说明,我们知道了为什么const 对象不能调用非const成员函数。

下面解释为什么const 对象可以调用const成员函数,

class test{public:void print()const;
};

前面我们把非const成员函数print(),翻译了一下,同样const成员函数也要翻译,void print()const;可以翻译成 void print(const test* this);,那么常量对象的地址翻译是const test* this; 是和void print() const;中this指针的类型是一样的,所以常量对象可以调用const成员函数

有一个点要注意,在c++中其实是有最小权限原则的,非const对象是可以调用const成员函数的。

任何不修改成员数据的函数应该声明为const函数,这样它可以由const对象使用。
**注意:**构造函数和析构函数都不是const成员函数,因为它们在初始化和清理时,总是对对象作些修改。

引申:如何在const成员函数里修改成员 —— 按位和与按成员const

如果我们想要建立一个const成员函数,但仍然想在对象里改变某些数据,这时该怎么办呢?这关系到按位const和按成员const的区别。按位const意思是对象中的每个位是固定的,所以对象的每个位映像从不改变。按成员const意思是,虽然整个对象从概念上讲是不变的,但是某个成员可能有变化。当编译器被告知一个对象是const对象时,它将保护这个对象。

这里我们要介绍在const成员函数里改变数据成员的两种方法。

1. 强制转换const

第一种方法已成为过去,称为“强制转换const”。它以相当奇怪的方式执行。取this(这个关键字产生当前对象的地址)并把它强制转换成指向当前类型对象的指针。看来this已经是我们所需的指针,但它是一个const指针,所以,还应把它强制转换成一个普通指针,这样就可以在运算中去掉常量性。下面是一个例子:

class Y {int i, j;
public:Y() { i = j = 0; }void f() const;
};void Y::f() const {//!i++; // error((Y*)this)->j++; // ok , cast away const feature.
}

这种方法可行,在过去的程序代码里可以看到这种用法,但这不是首选的技术。问题是:this没有用const修饰,这在一个对象的成员函数里被隐藏,这样,如果用户不能见到源代码(并找到用这种方法的地方),就不知道发生了什么

2. 关键字mutable

第二种方法也是推荐的方法,就是在类声明里使用关键字mutable,以指定一个特定的数据成员可以在一个const对象里被改变。

class Y {int i;mutable int j;
public:Y() { i = j = 0; }void f() const;
};void Y::f() const {//!i++; // error((Y*)this)->j++; // ok , mutable.
}

引申:类成员函数调用成员变量

1)const成员函数可以访问非const对象的非const数据成员、const数据成员,也可以访问const对象内的所有数据成员;

2)非const成员函数可以访问非const对象的非const数据成员、const数据成员,但不可以访问const对象的任意数据成员;
如果是通过入参的形式,则非const成员函数可以调用const对象的数据成员
例如:

class Test {public:Test(int i,int j) :value(i), non_const(j) {};void test(const Test t1) const { t1.value; }void test0(const Test& t1) const { t1.value; }void test1(const Test t) { t.value; }void test2(Test t2) { t2.value; }private:const int value;int non_const;
};

这是可以通过编译的

总结

  1. const对象只能调用const成员函数、不能调用非const成员函数;
  2. 非const对象可以调用const成员函数。

文章参考了:
https://blog.csdn.net/qq_33726635/article/details/105200480
https://blog.csdn.net/nawuyao/article/details/52748747?depth_1-
https://www.cnblogs.com/cplinux/p/5553716.html

const对象不能调用非const成员函数相关推荐

  1. const指针强转为非const指针后的赋值问题

    #include <iostream>using namespace std;int main() {const int a = 5;const int * p = &a;int ...

  2. const对象只能调用const成员函数、不能调用非const成员函数;非const对象可以调用const成员函数

    引发原因: 由调用成员函数时隐式传入的当前对象的this指针引起. 1. 非const成员函数中的隐式参数:classA* this 2. const成员函数中的隐式参数:const classA* ...

  3. 一文带你入门C++,类与对象、6个默认成员函数、this指针以及static关键字。

    C++98关键字:63个 一.命名空间规则(namespace) 1.命名空间可以解决函数.全局变量名重复的问题,包在不同的命名空间里的重复函数,实际就是两个完全无关的函数. 2.命名空间允许续嵌套: ...

  4. 成员函数的选择调用一一常成员函数 (12 分)

    成员函数的选择调用一一常成员函数 (12 分) 类中的常对象选择调用常成员函数.语法要点: 如果将一个对象说明为常对象,则通过该常对象只能调用它的常成员函数, 而不能调用其他成员函数.补充完整复数类的 ...

  5. 【Kotlin】扩展函数 ( 扩展函数声明 | 调用方式 | 与成员函数优先级 | 接收者空值处理 )

    文章目录 I . 扩展函数 总结 II . 扩展函数概念简介 III . 扩展函数简单示例 IV . 扩展函数调用选择方式 : 静态解析 V . 扩展函数 调用优先级 VI . 扩展函数 接收者 空值 ...

  6. 使用C#调用非托管DLL函数

    由于工作需要,学习了GDI+编程的一些知识.其中看到了一个比较好的Demo,深入的了解后,却发现自己对如何用C#调用非托管DLL函数也有了更好的理解,于是整理了一下,跟大家一起分享. 引用: 用C#来 ...

  7. 如何区分“指向const对象的指针”和“const指针”?

    const是C++中引入的一个新的关键字,它为C++编程带来了很大的方便.指向const对象的指针和const指针是两个名字很接近的概念,对于初学者来说非常容易搞混,这里对它们进行区分. 指向cons ...

  8. 函数指针调用类的成员函数

    1 在每个被调用函数之前加上static, 可以使成员函数脱离对象信息单独存在,虽然它属于这个类,但是没有附带上对象信息,但是前提是,static成员函数不能使用对象的信息(成员和函数). 2 使用一 ...

  9. 同一类的不同对象,在调用相同的成员函数时,入口地址是相同的

    一般成员函数的第一个参数默认是this(可以不写),this指针指向调用这个函数的对象,所以可以给函数传入不同的参数,输出不同的值,而且互不影响. 但是静态成员函数没有this指针. 定义的对象,编译 ...

最新文章

  1. 结对编程--基于android平台的黄金点游戏
  2. Swift进阶_第一部分
  3. MyBufferedReader
  4. 重庆计算机学校电话号码,重庆计算机学校
  5. ES的多种搜索机制:query string search,query DSL,query filter,full-text search,phrase search,highlight search
  6. python整型图_python源码研究之整型对象探索
  7. linux安装mysql不成功怎么处理_Linux上安装MySQL时出现不兼容的解决办法
  8. 大端字节序与小端字节序的转换
  9. Django中使用CORS实现跨域请求
  10. 自然语言处理包pytorch、torchvision、torchtext安装(亲测有效)
  11. 【Elasticsearch】es 5.3.0 bulk index 性能调优实践
  12. SqlServer存储过程基础
  13. 手把手教你protel 99se 入门
  14. 文件上传和下载的常用测试点
  15. 在vscode中打开PDF文件
  16. GIAC全球互联网架构大会2017上海站圆满结束,PPT合集下载
  17. excel组合汇总_Excel汇总20150112
  18. 解析智能推荐系统开发中十大关键要素
  19. 写在清明(2007年)
  20. 华为服务器imana安装系统,华为服务器imana配置

热门文章

  1. 智能机计算机在线用,高通骁龙7c/8c/8cx计算平台发布:为始终在线的PC打造
  2. 小虎电商浏览器:卖家精灵产品监控每日库存如何使用
  3. C语言1到n while语句
  4. 半入耳式耳机好用吗?游戏半入耳式耳机推荐
  5. Excel与minitab的不同
  6. 戴琼海院士:5年后大模型将成为AI的操作系统!
  7. 【深度学习】经典卷积神经网络结构说明
  8. 关于印度外包的情况:以及坐井观天的危险
  9. 【评测】胎牛血清/血清怎么选?
  10. 2D游戏入门——小狐狸系列(十四)添加人物受伤动画