C++ this指针

demystify 2014-06-08 01:06:19
本人在总结this指针的问题,对于网上的一个著名问题了解一些,但是自认为还不够透彻,在此发帖,希望能解决我的困惑

class A
{
private:
int i;
public:
virtual void fun(int a)
{
i = a;
cout<< i <<endl;
}
}
class B : public A
{
private:
int b;
public:
virtual void fun(int a)
{
b = a;
cout<< b <<endl;
}
}

void fun_test(B* const pThis, int a)
{
pThis->b = a;
cout<<pThis->b <<endl;
}

调用:
B b;
A* p = &b;
p->fun(2);
A a = (A)b;
a.fun(1);
fun_test(p, 1);//error
fun_test(&b, 2);//OK

上述问题我在网上找到很多,解释也基本能懂,我困惑的是:
(1)、关于p->fun(2),编译器在编译的时候,这句代码被编译成什么样子,隐含的this指针是什么时候,以及怎样传递给函数fun的?
(2)、关于fun_test(&b, 2),编译器在编译时会做什么?
(3)、关于fun_test(p, 1),编译器在编译的时候,是在什么时候进行类型规则检查的?
...全文
398 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
Adol1111 2014-06-10
  • 打赏
  • 举报
回复
引用 18 楼 xiaoxiaoyusheng2012 的回复:
[quote=引用 16 楼 Adol1111 的回复:] 1、this不是对象的成员,仅仅是一个表示自身的标示符,或者说是一个只想自己的一个指针。编译器在对象初始化的时候会把地址压入栈中,在需要的时候在取出来。 2、p->fun(2)实际被编译器替换成了 nomember的形式,等价于fun(p,2),具体详情看《Inside the C++ Object Model》第四章 关于你的语法错误我就不多说了,自己再好好复习一下
《Inside the C++ Object Model》书中描述,成员函数p->fun(2)会被改写为唯一的外部函数,改写后的原型应该为:extern fun_xxx(register B* const this), 函数调用相当于fun(p, 2),但是在我的代码中p是A*类型的,fun(p,2)存在语法错误,我猜测是不是函数最终的调用与“fun((B*)p, 2)”等价?这样解释合理吗?[/quote] 虚函数实际转化为(*p->vptr[1])(p,2),也就是根据虚表查找fun
demystify 2014-06-10
  • 打赏
  • 举报
回复
引用 16 楼 Adol1111 的回复:
1、this不是对象的成员,仅仅是一个表示自身的标示符,或者说是一个只想自己的一个指针。编译器在对象初始化的时候会把地址压入栈中,在需要的时候在取出来。 2、p->fun(2)实际被编译器替换成了 nomember的形式,等价于fun(p,2),具体详情看《Inside the C++ Object Model》第四章 关于你的语法错误我就不多说了,自己再好好复习一下
《Inside the C++ Object Model》书中描述,成员函数p->fun(2)会被改写为唯一的外部函数,改写后的原型应该为:extern fun_xxx(register B* const this), 函数调用相当于fun(p, 2),但是在我的代码中p是A*类型的,fun(p,2)存在语法错误,我猜测是不是函数最终的调用与“fun((B*)p, 2)”等价?这样解释合理吗?
赵4老师 2014-06-10
  • 打赏
  • 举报
回复
引用 14 楼 yingzijuntuan 的回复:
我觉得我现在比较暴力,不好传递的变量,就弄成全局变量。。。。
请牢记:源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要,重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。
Adol1111 2014-06-10
  • 打赏
  • 举报
回复
1、this不是对象的成员,仅仅是一个表示自身的标示符,或者说是一个只想自己的一个指针。编译器在对象初始化的时候会把地址压入栈中,在需要的时候在取出来。 2、p->fun(2)实际被编译器替换成了 nomember的形式,等价于fun(p,2),具体详情看《Inside the C++ Object Model》第四章 关于你的语法错误我就不多说了,自己再好好复习一下
超级能量泡泡 2014-06-10
  • 打赏
  • 举报
回复
引用 14 楼 yingzijuntuan 的回复:
我觉得我现在比较暴力,不好传递的变量,就弄成全局变量。。。。
可以专门搞个class,用静态成员变量来存放这种东西
yingzijuntuan 2014-06-09
  • 打赏
  • 举报
回复
我觉得我现在比较暴力,不好传递的变量,就弄成全局变量。。。。
赵4老师 2014-06-09
  • 打赏
  • 举报
回复
《深度探索C++对象模型》 《C++反汇编与逆向分析技术揭秘》 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行!
demystify 2014-06-09
  • 打赏
  • 举报
回复
楼上的方法确实不错,反汇编代码如下:

	B b;       
0127149E  lea         ecx,[b]  
012714A1  call        B::B (12710FFh)  
    A* p = &b;       
012714A6  lea         eax,[b]  
012714A9  mov         dword ptr [p],eax  
    p->fun(2);      
012714AC  mov         esi,esp  
012714AE  push        2  
012714B0  mov         eax,dword ptr [p]  
012714B3  mov         edx,dword ptr [eax]  
012714B5  mov         ecx,dword ptr [p]  
012714B8  mov         eax,dword ptr [edx]  
012714BA  call        eax  
012714BC  cmp         esi,esp  
012714BE  call        @ILT+360(__RTC_CheckEsp) (127116Dh)  
    A a = (A)b;      
012714C3  lea         eax,[b]  
012714C6  push        eax  
012714C7  lea         ecx,[a]  
012714CA  call        A::A (127119Ah)  
    a.fun(1);       
012714CF  push        1  
012714D1  lea         ecx,[a]  
012714D4  call        A::fun (12711CCh)  
    //fun_test(p, 1);//error      
    fun_test(&b, 2);//OK
012714D9  push        2  
012714DB  lea         eax,[b]  
012714DE  push        eax  
012714DF  call        fun_test (1271195h)  
012714E4  add         esp,8  
	return 0;
汇编没学好,看不太明白。。。。
xiaohuh421 2014-06-09
  • 打赏
  • 举报
回复
B b; //在这句下个断点. A* p = &b; p->fun(2); A a = (A)b; a.fun(1); fun_test(p, 1);//error fun_test(&b, 2);//OK 当程序运行到断点处, 然后: 菜单-->调试-->窗口-->反汇编 即可查看下面每一句代码的反汇编. 这时你就可以看到this指针是怎么传的了.
demystify 2014-06-09
  • 打赏
  • 举报
回复
B* const pThis, pThis是常量, pThis指向的内容不是常量, 所以这是没问题的,我这里写错的地方是不可以在类外部直接访问类的私有成员。
子夜一段星 2014-06-09
  • 打赏
  • 举报
回复
这代码能通过不?const常量怎么能通过函数改变其值呢?我看不懂
敬畏者 2014-06-08
  • 打赏
  • 举报
回复
fun_test(p, 1);//error 之所以错误是因为需要强制类型转换 fun_test((B*)p, 1);
敬畏者 2014-06-08
  • 打赏
  • 举报
回复
都是等价的吧
demystify 2014-06-08
  • 打赏
  • 举报
回复
可能是因为我不懂编译技术原因,不知道c++代码时如何一步步变成汇编代码的,所以对问题描述不清,简单地说,我就是想知道,p->fun(2)和fun_test(p, 1)以及fun_test(&b, 2)在编译的时候有什么区别?如果说“p->fun(2)”和“p->fun(p, 2)”等价,为什么前者可以编译通过而后者不可以, 如果说“p->fun(2)”和“p->fun(&b, 2)”等价,那么&b从何而来?如果都不等价,那么对于p->fun(2),在编译的整个过程中,this指针是如何介入的?
敬畏者 2014-06-08
  • 打赏
  • 举报
回复
因为你的问题就莫名其妙,所以不好回答 这句代码被编译成什么样子:编译成汇编,你看反汇编代码 隐含的this指针是什么时候:什么时候?,什么叫什么时候 以及怎样传递给函数fun的:通常是ECX传递,但不是必须的,我知道你的重点不是这个 可是你的问题就糊里糊涂,你得先搞明白自己的问题是什么f
demystify 2014-06-08
  • 打赏
  • 举报
回复
呵呵, 不好意思这里写错了,通过fun_test只是想模拟一下this指针的操作,fun_test应该改为: void fun_test(B* const pThis, int a) { pThis->fun(a); } 不过,我的问题焦点不是这个。
lm_whales 2014-06-08
  • 打赏
  • 举报
回复
这个OK不了
Morrisss_ 2014-06-08
  • 打赏
  • 举报
回复
还有,你确定fun_test能执行?既不是成员,也不是友元,直接访问修改私有成员。
Morrisss_ 2014-06-08
  • 打赏
  • 举报
回复
http://blog.csdn.net/tobebetterprogrammer/article/details/29247029 看看这个。

64,651

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧