memset() 初始化类对象

今天看到迅雷2014校招一道笔试题如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <iostream>  
  2. using namespace std;  
  3.   
  4. class parent  
  5. {  
  6. public:  
  7.     virtual void output();  
  8. };  
  9. void parent::output()  
  10. {  
  11.     printf("parent!");  
  12. }  
  13.   
  14. class son : public parent  
  15. {  
  16. public:  
  17.     virtual void output();  
  18. };  
  19. void son::output()  
  20. {  
  21.     printf("son!");  
  22. }  
  23.   
  24. int main()  
  25. {  
  26.     son s;  
  27.     memset(&s , 0 , sizeof(s));  
  28.     parent& p = s;  
  29.     p.output();  
  30.     return 0;  
  31. }  

输出程序运行结果:程序不输出结果,运行出错!!分析一下原因:

在使用memset初始化对象Obj之前,通过Obj调用Show和Print函数时程序运行正常,但是一旦利用Memset函数初始化该对象,再对该obj调用Show和Print函数,则程序立马崩溃。究其原因是因为初始化obj的时候,将obj包含的指向虚函数表VTBL的指针也清除了。包含虚函数的类对象都有一个指向虚函数表的指针,此指针被用于解决运行时和动态类型强制转换时虚函数的调用问题。该指针是被隐藏的,对程序员来说,这个指针也是不可存取的。当进行memset操作时,这个指针(即指向虚函数表的地址)的值也要被初始化,这样一来,只要一调用虚函数,程序便会崩溃。
这种现象在很多由C转向C++的程序员来说,很容易犯这个错误,而且这个错误很难查。

为了避免这种情况,记住对于有虚拟函数的类对象,决不能使用memset来进行初始化操作。而是要用缺省的构造函数或其它的init例程来初始化成员变量。


当类中有虚函数的时候,编译器会为类插入一个我们看不见的数据并建立一个表。这个表就是虚函数表(vtbl),那个我们看不见的数据就是指向虚函数表的指针——虚表指针(vptr)。虚函数表就是为了保存类中的虚函数的地址。我们可以把虚函数表理解成一个数组,数组中的每个元素存放的就是类中虚函数的地址。当调用虚函数的时候,程序不是像普通函数那样直接跳到函数的代码处,而是先取出vptr即得到虚函数表的地址,根据这个来到虚函数表里,从这个表里取出该函数的地址,最后调用该函数。所以只要不同类的vptr不同,他对应的vtbl就不同,不同的vtbl装着对应类的虚函数地址,这样虚函数就可以完成它的任务了。



合并两家说法

http://blog.csdn.net/huruzun/article/details/28272487

http://blog.csdn.net/lishengwei/article/details/2416847

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Car12

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值