| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2836 人关注过本帖
标题:关于const成员函数的几个不解?
只看楼主 加入收藏
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
结帖率:90.24%
收藏
已结贴  问题点数:20 回复次数:8 
关于const成员函数的几个不解?
图片附件: 游客没有浏览图片的权限,请 登录注册


我的理解如下:
    如上图,const成员函数可以认为修改了this指针的类型,将this指针类型由classType * const类型转换为 classType const * const类型,因此const成员函数可以访问常量对象,而
非const成员函数则不行。但是请问为何非const成员函数可以访问const成员呢?那岂不是相当于classType * const pt = &(常量),这个在语法上是错误的呀?不是非常指针不能指向常量嘛,
求大佬帮助!

搜索更多相关主题的帖子: const 成员 函数 指针 常量 
2018-04-02 20:04
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
收藏
得分:0 
第二个问题:
图片附件: 游客没有浏览图片的权限,请 登录注册


里面对于派生类类内的修改情况是不是有点问题呢?

程序代码:
#include <iostream>
#include <vector>
#include <string>

using namespace std;

class A
{
protected:
    int pa;    
};

class B :protected A
{
public:
    void setPa()
    {
        pa = 10;
    }
};

int main()
{
    B b;
    
    b.setPa();

    system("pause");
    return 0;
}


比如以上代码,我就能在派生类内修改protected成员撒~

请问是不是上面这位仁兄总结的表格有问题呢? 感激不尽哈~

[此贴子已经被作者于2018-4-3 00:09编辑过]


既然还有不甘心
就还没到放弃的时候~
2018-04-02 20:31
Jonny0201
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:52
帖 子:488
专家分:2603
注 册:2016-11-7
收藏
得分:0 
回答你第二个问题先
protected 继承后, 原来的类里的 protected 成员在新的类里仍然是 protected
把 B 类写完整就是
class B :protected A
{
protcted:
    int pa;        //从 A 继承过来
public:
    void setPa()
    {
        pa = 10;
    }
};
2018-04-03 12:26
Jonny0201
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:52
帖 子:488
专家分:2603
注 册:2016-11-7
收藏
得分:0 
你的第一个问题我理解的不是很清楚
你是说在非 const 成员方法里面访问 const 成员属性是吗?
也就是
class Foo {
private:
    const int a {1};
public:
    void func() {
        cout << a<< endl;
}
类似于这种?
这种本来就是可以的啊
2018-04-03 12:30
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
收藏
得分:0 
回复 4楼 Jonny0201
因为c++ primer上讲到了一般成员函数中的this指针本身是一个常指针,类型为Type* const ptr,而const成员函数相当于将this只能再次进行强化为const Type* const ptr,即变成了只想常量对象的常量指针。
但是非const成员函数依然能访问类的const成员,在我的理解中就类似于以下操作:
Type* const ptr = &(常量)  
______ 此操作与以下操作类似 ______
const int elem = 10;
int *pt = &elem;
下面明显是不对的撒,为啥上面的确可以访问呢?
求大佬给解答一二,不胜感激!


[此贴子已经被作者于2018-4-4 11:58编辑过]


既然还有不甘心
就还没到放弃的时候~
2018-04-04 11:57
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
收藏
得分:0 
回复 3楼 Jonny0201
嗯 所以说上面别人总结的那个表表是错误的咯!

还是在CSDN上看到的~!

既然还有不甘心
就还没到放弃的时候~
2018-04-04 11:59
枫林火山
Rank: 2
来 自:XX县高一学生一只
等 级:论坛游民
威 望:3
帖 子:15
专家分:96
注 册:2017-2-10
收藏
得分:10 
我来说说第一个问题吧。

为什么非const成员函数能访问const常量对象?

首先根据LZ给出的一段代码,
const int elem = 10;
int *pt = &elem;
这段代码真的不可以吗?
我们是不是可以换一种思路呢?不过要考虑编译器对于const int elem的实现了。
比如我们看看这段代码。

程序代码:
#include <iostream>


int main()
{
    const int a = 20;
    std::cout << a << std::endl;
    system("pause");
    return 0;
}


编译后产生了什么呢?

图片附件: 游客没有浏览图片的权限,请 登录注册


注意push 0x14,const int a = 20;,a没有被保存在堆栈里面,而是直接作为立即数传参了。所以楼主给出的那段通过指针修改const变量是不能运行的。
这只是我的一个随便说法,当然如此说来也是有点牵强。
进行Patch之后呢?
图片附件: 游客没有浏览图片的权限,请 登录注册


嗯……上面我想说明什么?我也不知道我想说明什么。

我只是想阐明一个我认为的道理。既然玩的语言支持Native Code编译,不是基于虚拟机执行的。我只以ASM为标准,从来不会理编译器的规定的。

我们再脑洞打开进行一次作死修改a的值的尝试如何?

图片附件: 游客没有浏览图片的权限,请 登录注册


程序代码:
#include <iostream>
#include <windows.h>

int main()
{
    DWORD dwFlag;
    BYTE bCode[2] = {0x6A, 0xC}; //push 0xC
    PBYTE p = PBYTE(&main);
    const int a = 0xC; //十进制的12
    
    VirtualProtect(p, 100, PAGE_EXECUTE_READWRITE, &dwFlag);
    
    while (memcmp(bCode, p, 2))
        p++;
    p++;
    __asm
    {
        mov eax,p
        mov byte ptr[eax],0x50
    }

    std::cout << a << std::endl;
    system("pause");
    return 0;
}


(VC6编译器)

回到本源吧。const限定符,我的理解是不允许修改,没有不允许读取。嗯,总而言之,就是这么一句话。前面写的我也不知道自己在说什么。。。。哇咔咔咔,各位拍砖轻点。
const成员函数,只是表明自己不修改,没有规定不读取。至于LZ的理解,我个人觉得没必要这么复杂化。学了汇编以后就不会按照这个思路去思考了。

大丈夫久居人下,生死等闲,顺风则行,逆风则泊?
我欲上九天揽月,痛饮狂欢,宁斗而败,不屈而活!
一朝得势自比天,挥斥方遒,有何罡碍,有何不可?
我志在万世功业,名扬天下,宁鸣而生,不默而死!
2018-04-04 21:13
Jonny0201
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:贵宾
威 望:52
帖 子:488
专家分:2603
注 册:2016-11-7
收藏
得分:10 
回复 5楼 S140131022
我的想法不同于上面汇编大佬的想法 (我真的看不懂啊
在类中 this 指针其实是
T *const this

this 其实是一个右值指针
根据 C++ 标准 : 一个 T 类型的右值指针可以被隐含地添加 const 限定
也就是说, 在编译的过程中, 编译器帮你对 *this 也进行了 const 限定
也就是这样的
const T *const this

此时再访问被 const 限定的成员就没问题了

这段代码明显是可以通过编译的 :
程序代码:
#include <iostream>

using namespace std;
int main(int argc, char *argv[]) {
    const int a = 1;
    const int *const p = &a;
}


不知道其他大神还有没有想法
其实我也觉得纠结这个完全没必要, 除非写 C++ 编译器
2018-04-05 11:35
S140131022
Rank: 2
来 自:重庆邮电大学
等 级:论坛游民
帖 子:205
专家分:35
注 册:2014-10-9
收藏
得分:0 
回复 7楼 枫林火山
总结一下吧: 不纠结了 感觉自己钻了牛角尖

在使用C++语言开发中,如果我们希望某一个对象在定义之后不被错误的修改,我们可以将这个对象声明为const对象,这样这个对象的数据成员就不可以被更改。

1.定义const对象

const 类名 对象名;

  类名 const 对象名;

1)定义类对象时可以将其指定为const对象。定义后const对象不能再被修改;

2)const对象不能调用非const类型的成员函数。

  在非const成员函数内部,有可能会对对象的数据成员进行修改,比如setHour()修改了对象的Hour值。而const类型的成员函数是不会修改对象的数据成员的。

const数据成员

1.const数据成员

  在类内部使用const关键字来声明const数据成员。const数据成员的值不能被修改。

const int m_nNum;//定义了一个const数据成员

  初始化时比较特殊,只能通过初始化列表初始化。不能在构造函数里赋值。

2.初始化列表

  构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。

  初始化列表可以为数据成员初始化,不仅仅只是const数据成员。

  我们在构造函数外面添加了初始化列表,这个列表里面为const成员m_nNum赋了初始值10,如果我们有多个构造函数,必须在每一个构造函数外面都对这个const成员添加初始化列表初始化,包括复制构造函数。

 

const成员函数

1.const成员函数只能被const对象引用;

2.const成员函数内可以引用const数据成员,也可以引用非const数据成员,但不能修改非const数据成员的值,也不能调用非const成员函数;

3.const成员函数在声明和定义的时候都必须加上const。

[此贴子已经被作者于2018-4-5 11:55编辑过]


既然还有不甘心
就还没到放弃的时候~
2018-04-05 11:47
快速回复:关于const成员函数的几个不解?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.023957 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved