| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2160 人关注过本帖
标题:强转指针导致虚函数表丢失?
只看楼主 加入收藏
fg5823820
Rank: 2
等 级:论坛游民
帖 子:9
专家分:25
注 册:2012-1-3
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:12 
强转指针导致虚函数表丢失?
百度了很多关于虚函数表的文章,都讲解了虚函数表的原理,看得一知半解,目前没法解决我遇到的问题:
程序代码:
#include <string>
#include <iostream>
using namespace std;

struct A
{
    virtual void FunA() = 0;
};

struct C : public A
{
    C():num(1000){}
    virtual void FunA()
    {
        cout<<"FunA:"<<num*num<<endl;
    }

    long num;
};

int _tmain(int argc, _TCHAR* argv[])
{
    C* c = new C;
    A* a;
    void* p = c;
    a = (A*)p;
    a->FunA();
    delete c;
    return 0;
}
打印的时候开起来没有任何错误,不过调试就会发现虚表是错误的。

我最困惑的地方是:
1、有时候这样转换是没有问题的,有时候就会出问题。
2、虚表到底是保存在什么位置?为什么转成别的类型指针后虚表会丢失?
搜索更多相关主题的帖子: 文章 百度 public 虚函数 
2012-01-03 21:54
鑫乐源
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:27
专家分:150
注 册:2011-10-20
收藏
得分:3 
解释起来太麻烦,涉及C++对象内存布局
下面的这个链接可以解释一部分,粗略的
https://hi.bccn.net/space-459307-do-blog-id-32857.html

不要和编译器比智商。
2012-01-03 23:35
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9031
专家分:54061
注 册:2011-1-18
收藏
得分:0 
代码没问题,又不是多重继承

除了应该将 int _tmain(int argc, _TCHAR* argv[])
改为 int main(int argc, char* argv[]) 之外
不要将某个编译器特有的东西带到C++中来
2012-01-04 08:21
fg5823820
Rank: 2
等 级:论坛游民
帖 子:9
专家分:25
注 册:2012-1-3
收藏
得分:0 
回复 3楼 rjsp
改成int main并再次尝试了,这是结果
[IMG]http://img165.[/IMG]
2012-01-04 09:55
fg5823820
Rank: 2
等 级:论坛游民
帖 子:9
专家分:25
注 册:2012-1-3
收藏
得分:0 
回复 2楼 鑫乐源
其实我正是遇到与那个帖子相同的问题,最初遇到问题的时候就是在多继承的时候,后来去试了一下,并非只有在多继承的时候才会发生。

我给出的代码里原来还有个B接口,C同时继承A和B,总是有一个接口强转失败(A接口),刚开始认为是继承顺序导致,后来果断去掉B接口,只继承A接口,发现一样强转失败,目前能解决这个问题的唯一方法,就是将void*先转成C*,再转成任何C继承任何父类,更复杂的情况没有去尝试。虚表这东西还真搞不懂其实我正是遇到与那个帖子相同的问题,最初遇到问题的时候就是在多继承的时候,后来去试了一下,并非只有在多继承的时候才会发生。

我给出的代码里原来还有个B接口,C同时继承A和B,总是有一个接口强转失败(A接口),刚开始认为是继承顺序导致,后来果断去掉B接口,只继承A接口,发现一样强转失败,目前能解决这个问题的唯一方法,就是将void*先转成C*,再转成任何C继承任何父类,更复杂的情况没有去尝试。虚表这东西还真搞不懂
2012-01-04 10:01
鑫乐源
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:27
专家分:150
注 册:2011-10-20
收藏
得分:17 
似乎在哪里看到过说,不同的c++编译器出来的对象内存布局可能也不同,主要是虚函数表这东西的位置。如果你知道void*之后可能转换成的类型,那么在void*之前应该传递该类型的基类类型,比如 void* p = (A*)c;,一般不会出错,你自己验证一下吧

不要和编译器比智商。
2012-01-05 23:36
fg5823820
Rank: 2
等 级:论坛游民
帖 子:9
专家分:25
注 册:2012-1-3
收藏
得分:0 
回复 6楼 鑫乐源
的确这样虚表就不会错了,非常感谢,试了多继承也没问题,看来虚表这东西要好好研究研究
2012-01-06 09:41
flyxkj
Rank: 2
等 级:论坛游民
帖 子:15
专家分:66
注 册:2012-1-31
收藏
得分:0 
编译器用的什么哦!用g++编译器不会有任何问题!
2012-02-01 10:50
湿柴
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2012-2-1
收藏
得分:0 
看不懂啊···
2012-02-01 13:07
fg5823820
Rank: 2
等 级:论坛游民
帖 子:9
专家分:25
注 册:2012-1-3
收藏
得分:0 
回复 8楼 flyxkj
你可以试试这段代码,看看打印结果
程序代码:
struct A
{
    virtual void FunA() = 0;
};

struct B
{
    virtual void FunB() = 0;
};

struct C : public A, public B
{
    C():num(1000){}
    virtual void FunA()
    {
        cout<<"FunA:"<<num*num<<endl;
    }

    virtual void FunB()
    {
        cout<<"FunB:"<<num*num<<endl;
    }

    long num;
};

int main()
{
    C* c = new C;
    A* a;
    void* p = c;
    a = (A*)p;
    a->FunA();

    B* b;
    b = (B*)p;
    b->FunB();


    delete c;
    return 0;
}
2012-02-27 16:24
快速回复:强转指针导致虚函数表丢失?
数据加载中...
 
   



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

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