自杀式多重继承

作者在 2011-01-02 01:32:32 发布以下内容

template <typename T>
class InterfaceT
{
public:
    InterfaceT(void)
    {
    }
    virtual ~InterfaceT(void) = 0
    {
    }

    T    t;
};

class InterfaceA
{
public:
    virtual ~InterfaceA(void) = 0 {}
    virtual void TestFun1(void) = 0;
    virtual void TestFun2(void) = 0;

};

#define TEST 1

#if TEST == 1
class BigBen
    : public InterfaceT<int>
    , public InterfaceA
#else
class BigBen
    : public InterfaceA
    , public InterfaceT<int>
#endif

{
public:
    BigBen(void)
    {
    }
    virtual ~BigBen(void)
    {
    }
    virtual void TestFun1(void)
    {
        printf("TestFun1\n");
    }
    virtual void TestFun2(void)
    {
        printf("TestFun2\n");
    }

private:
    char    m_buf[3068];

};


void TestFun1(void* _p)
{
    ((InterfaceA*)_p)->TestFun1();
}
void TestFun2(void* _p)
{
    ((InterfaceA*)_p)->TestFun2();
}
int _tmain(int argc, _TCHAR* argv[])
{
    BigBen bb;
    TestFun1(&bb);
    TestFun2(&bb);

    system("pause");
    return 0;
}

 

一个void*可以秒杀一切吗?上面的测试程序不管TEST是1还是0都可以编译,但是如果TEST为1时运行就会出Access violation错误。凌晨1点半了,头晕。哪位高手帮忙解答!!谢谢

C++ | 阅读 1204 次
文章评论,共1条
迷失的木桶(作者)
2011-01-23 19:26
1
看样子我对C++对象认识还不够,经过我对代码的逐步调试,现在总算明白这是怎么一个回事。<br />
C++对象的内存布局是按照继承顺序排列的,因此<br />
class BigBen<br />
&nbsp; &nbsp; : public InterfaceT&lt;int&gt;<br />
&nbsp; &nbsp; , public InterfaceA<br />
的内存布局为<br />
InterfaceT : _vfptr&nbsp; &nbsp; (一个指针4字节)<br />
InterfaceT : int&nbsp; &nbsp;&nbsp; &nbsp; (一个整型4字节)<br />
InterfaceA : _vfptr&nbsp; &nbsp; (一个指针4字节)<br />
BigBen&nbsp; &nbsp;&nbsp;&nbsp;: char[3068]&nbsp;&nbsp;...<br />
<br />
调用 TestFun1(&amp;bb); <br />
通过反汇编可以看到:<br />
...<br />
((InterfaceA*)_p)-&gt;TestFun1();<br />
00A714CE&nbsp;&nbsp;mov&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;eax,dword ptr [_p] <br />
1、把对象地址存到eax;<br />
00A714D1&nbsp;&nbsp;mov&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;edx,dword ptr [eax] <br />
2、得到该对象地址的虚函数列表地址;<br />
...<br />
00A714D5&nbsp;&nbsp;mov&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;ecx,dword ptr [_p] <br />
3、ecx作为c++中的this指针;<br />
00A714D8&nbsp;&nbsp;mov&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;eax,dword ptr [edx+4] <br />
4、获得要调用的虚函数地址,这里为加4个字节;<br />
00A714DB&nbsp;&nbsp;call&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;eax&nbsp;&nbsp;<br />
5、调用虚函数。<br />
...<br />
<br />
由此可见,由于我给TestFun1函数的实参即为BigBen对象的首地址(InterfaceT : _vfptr),因此在TestFun1函数中通过((InterfaceA*)_p)得到的解引用地址是错误的,错误的解析成InterfaceA : _vfptr地址。<br />
<br />
解决方法是:<br />
InterfaceA* a = &amp;bb;<br />
&nbsp; &nbsp; TestFun1(a);<br />
&nbsp; &nbsp; TestFun2(a);
游客请输入验证码
最新评论