免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 2879 | 回复: 16
打印 上一主题 下一主题

[C++] 发生了什么事??!!C++高手请进 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-01-10 12:53 |只看该作者 |倒序浏览
代码有点长,如果你没耐心读完,请不要在此发言,谢谢合作!!
请帮我分析一下,下面作了标记的一句代码到底发生了什么事?
里面内容涉及VTABLE,模拟了通过VTABLE来调用指定的成员函数.


  1. //---------------------CODE From HERE--------------------
  2. #include <iostream>
  3. using namespace std;

  4. class C1{
  5.         public:
  6.                 C1(){};
  7.                
  8.                 void SetValue(int var1){
  9.                         mVal=var1;
  10.                 };

  11.                 virtual int PrintValue(){
  12.                         cout<<"In Class C1,Value="<<mVal<<endl;return 0;
  13.                 };

  14.                 virtual int PrintHello(){
  15.                         cout<<"Hello World!!(In C1!)"<<endl;return 0;
  16.                 };
  17.         protected:
  18.                 int mVal;
  19. };

  20. class C2: public C1{
  21.         public:
  22.                 C2():C1(){};

  23.                 int PrintValue(){
  24.                         cout<<"In Class C2,Value="<<mVal<<endl;return 0;
  25.                 };

  26.                 int PrintHello(){
  27.                         cout<<"Hello World!!(In C2!)"<<endl;return 0;
  28.                 };

  29. };

  30. int main() {
  31.         C1 obj1;
  32.         C2 obj2;
  33.         int (*pfn)(C1 *);//function pointer point to the member function
  34.         int **p; //a pointer point to the vtable
  35.        
  36.         //设置初值
  37.         obj1.SetValue(999);
  38.         obj2.SetValue(888);
  39.        
  40.         cout<<"------------------Obj1----------------"<<endl;
  41.         p=(int **) &obj1;

  42.         int var1=(int)*(p+1);//如果不要这一句,一切正常,没问题,如果执行了一这句就有问题了.

  43.         pfn=(int (*) (C1 *)) **p;
  44.         pfn(&obj1);//invoke member function printvalue;

  45.         pfn=(int (*) (C1 *)) *(*p+1);
  46.         pfn(&obj1);//invoke member function printhello;

  47.         cout<<"------------------Obj2----------------"<<endl;
  48.         p=(int **) &obj2;
  49.        
  50.         pfn=(int (*) (C1 *)) **p;
  51.         pfn(&obj2);

  52.         pfn=(int (*) (C1 *)) *(*p+1);
  53.         pfn(&obj2);

  54.         return 0;
  55. }
  56. //----------------------------End OF THE CODE-----------------------------
复制代码


有那一句的执行结果(不正确的结果):
------------------Obj1----------------
In Class C1,Value=4198685
Hello World!!(In C1!)
------------------Obj2----------------
In Class C2,Value=4198880
Hello World!!(In C2!)
没有那一句的结果(正确的结果):
------------------Obj1----------------
In Class C1,Value=999
Hello World!!(In C1!)
------------------Obj2----------------
In Class C2,Value=888
Hello World!!(In C2!)

注意,两个类的实例中的数据都发生了变化.经过调试发现实际内存中的数据并未发生变化(是正确的),应该是这个变量的地址出了问题.

论坛徽章:
0
2 [报告]
发表于 2006-01-10 14:01 |只看该作者
你用的什么编译器?我用的g++都是一样的正确结果.

论坛徽章:
0
3 [报告]
发表于 2006-01-10 14:33 |只看该作者

回复 2楼 converse 的帖子

哦,忘了说了,是VC++6.0.windows 2000操作系统

[ 本帖最后由 xie_jian_jun 于 2006-1-10 14:39 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2006-01-10 14:45 |只看该作者
VC6对标准的支持比较糟糕,建议你用mingw试试看,我就是用的这个...如果gcc下面没有问题的话应该不是你的问题,而是编译器的不同实现罢了.

论坛徽章:
0
5 [报告]
发表于 2006-01-10 14:53 |只看该作者

回复 4楼 converse 的帖子

嗯.谢谢.不过我只是想知道VC到底做了什么.调试了一下,头都大了.按理来说不该出现这样的情况才对的.

论坛徽章:
0
6 [报告]
发表于 2006-01-10 15:22 |只看该作者
看了下VC下面的汇编,pfn(&obj1)这里传进去的参数好象根本就没用.注掉int var1=(int)*(p+1)这一行能正确运行好象是个巧合.可能VC下面对于THIS指针和你这里直接传参进去有所不同。

论坛徽章:
0
7 [报告]
发表于 2006-01-10 15:27 |只看该作者
你在pfn=(int (*) (C1 *)) **p;前面随便加一些指针运算的代码,结果都会出错.

论坛徽章:
0
8 [报告]
发表于 2006-01-10 15:38 |只看该作者

回复 7楼 darkmoonnk 的帖子

就是这样子的.怎么回事.VC动了什么手脚.同意楼上说的传入的参数没有用上.不过为什么我注释掉那一句,他仍然找到了正确的对象.这又是怎么回事啊.不会只是巧合吧.

如果将调用成员函数的把给的参数&obj1替换成0,obj1的运行结果是正确的,但obj2就不正确了.

[ 本帖最后由 xie_jian_jun 于 2006-1-10 15:51 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2006-01-10 16:00 |只看该作者
你可以跟跟正常访问类成员函数的汇编代码,比如说obj1.printvalue(),看它是怎么编译的,估计编译的时候会有一些相应处理.而你这样直接访问这个函数的时候没有了这些处理,所以出错.

论坛徽章:
0
10 [报告]
发表于 2006-01-10 16:10 |只看该作者
原帖由 xie_jian_jun 于 2006-1-10 15:38 发表
就是这样子的.怎么回事.VC动了什么手脚.同意楼上说的传入的参数没有用上.不过为什么我注释掉那一句,他仍然找到了正确的对象.这又是怎么回事啊.不会只是巧合吧.

如果将调用成员函数的把给的参数&obj1替换成 ...


哈哈,这正说明是巧合啊.
不知道你所说的找到正确的对象是什么意识.C++程序编译了之后就没有对象的概念了,有的只是函数的地址.访问的时候跳到那个函数的地址,运行就可以了.而this指针可能是通过压栈或者别的什么处理方法来传给调用函数的.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP