memset() 初始化类对象

论坛 期权论坛 脚本     
匿名技术用户   2020-12-29 02:11   644   0

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

  1. #include <iostream>
  2. using namespace std;
  3. class parent
  4. {
  5. public:
  6. virtual void output();
  7. };
  8. void parent::output()
  9. {
  10. printf("parent!");
  11. }
  12. class son : public parent
  13. {
  14. public:
  15. virtual void output();
  16. };
  17. void son::output()
  18. {
  19. printf("son!");
  20. }
  21. int main()
  22. {
  23. son s;
  24. memset(&s , 0 , sizeof(s));
  25. parent& p = s;
  26. p.output();
  27. return 0;
  28. }

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

在使用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

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP