游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3386|回复: 12

C++里的多继承~不明白~

[复制链接]

38

主题

275

帖子

281

积分

中级会员

Rank: 3Rank: 3

积分
281
QQ
发表于 2006-3-10 14:11:00 | 显示全部楼层 |阅读模式
先贴代码:

#include <iostream>

using namespace std;

class CA
{
protected:
        int m_a;
public:
        CA(int a)        { m_a=a;        cout << "CA 构造函数" <<m_a<< endl;}
};

class CB:public CA
{
public:
        CB(int a):CA(a)        { cout << "CB 构造函数" <<m_a<< endl;}
};

class CC:public CA
{
public:
        CC(int a):CA(a) {cout << "CC 构造函数" <<m_a<< endl;}

};

class CD:private CB,private CC
{
public:
        inline void Display();
        CD(int a,int b):CB(a),CC(b)               
        {
                cout << "CD构造函数 " << endl;
        }

};

inline void CD:isplay()
{
        cout << "CB::m_a=" <<CB::m_a << endl;
        cout << "CC::m_a=" << CC::m_a << endl;
        //cout << "CA::m_a=" << CA::m_a << endl;
}

int main()
{
        CD  cd(10,20);
        cd.Display();
       
        return 0;

}
//为什么DIspaly中的注释行是错的?这其中的道理是什么?

18

主题

573

帖子

573

积分

高级会员

Rank: 4

积分
573
发表于 2006-3-10 15:38:00 | 显示全部楼层

Re:C++里的多继承~不明白~

我用vc++2005EE运行以上的程序,把注释行去掉后,可以运行的!显示CA::m_a=10

11

主题

162

帖子

189

积分

注册会员

Rank: 2

积分
189
QQ
发表于 2006-3-10 16:09:00 | 显示全部楼层

Re:C++里的多继承~不明白~

错误信息:

whistler@www:~$ g++ 1.cpp
1.cpp: In member function 'void CD:isplay()':
1.cpp:49: error: 'CA' is an ambiguous base of 'CD'

也就是说,不知道 CA 是从 CB 继承 的, 还是从 CC 继承的。

38

主题

275

帖子

281

积分

中级会员

Rank: 3Rank: 3

积分
281
QQ
 楼主| 发表于 2006-3-10 22:34:00 | 显示全部楼层

Re:C++里的多继承~不明白~

  3楼的错误信息和我一样~~编译器认为那个CA::m_a是具有二义性的~~
  2楼的,在2005里它认为是正确的,那又是为什么?标准C++认为该是怎么样的结果呢?

18

主题

279

帖子

279

积分

中级会员

Rank: 3Rank: 3

积分
279
QQ
发表于 2006-3-11 09:04:00 | 显示全部楼层

Re:C++里的多继承~不明白~

按标准确实存在二义性。
但是跨级访问本身就是不必要的。
如果祖类成员可被访问,则它一定可通过某一父类访问。

3楼的错误信息贴的不全吧 [em2](只贴了error)
老版本的VC6给出的:
error : 'CD::CA' is ambiguous
warning : could be the 'CA' in base 'CB' of class 'CD'
warning : or the 'CA' in base 'CC' of class 'CD'
这多清楚吗!

38

主题

275

帖子

281

积分

中级会员

Rank: 3Rank: 3

积分
281
QQ
 楼主| 发表于 2006-3-11 12:17:00 | 显示全部楼层

Re:C++里的多继承~不明白~

~了解~

57

主题

970

帖子

994

积分

高级会员

Rank: 4

积分
994
发表于 2006-3-11 22:18:00 | 显示全部楼层

Re:C++里的多继承~不明白~

学习~

18

主题

573

帖子

573

积分

高级会员

Rank: 4

积分
573
发表于 2006-3-12 00:23:00 | 显示全部楼层

Re:C++里的多继承~不明白~

    我没有在其它的编译器上运行,只在vs2005EE上运行了,结果是10, 20, 10。
    我的理解是继承是堆砌的结果,而只有CA定义了m_a,而其它的派生类都没有定义任何变量,CD第一个继承的就是CB,而CB继承自CA,因为其它的派生类没有定义任何变量,所以使用CD::m_a和使用CA::m_a是同一个位置的变量,而因为CD第二个继承CC,所以CC会堆砌在CB的下面(因为先继承的是CB嘛),显示CC::m_a的值会是20。
    以上是我个人的理解,请大家指正!

38

主题

275

帖子

281

积分

中级会员

Rank: 3Rank: 3

积分
281
QQ
 楼主| 发表于 2006-3-12 00:59:00 | 显示全部楼层

Re:C++里的多继承~不明白~

最变态的方法,有没有牛人精通汇编的~~把代码输出成汇编文件~看看数据是如何排列的~~牛人帮忙~

18

主题

573

帖子

573

积分

高级会员

Rank: 4

积分
573
发表于 2006-3-12 02:08:00 | 显示全部楼层

Re:C++里的多继承~不明白~

        cout << "CB::m_a=" <<CB::m_a << endl;
0043E5D3  push        offset std::endl (43A7DAh)
0043E5D8  mov         eax,dword ptr [this]        A
0043E5DB  mov         ecx,dword ptr [eax]         B
0043E5DD  push        ecx  
0043E5DE  push        offset string "CB::m_a=" (4B4240h)
0043E5E3  push        offset std::cout (4CA068h)
0043E5E8  call        std:perator<<<std::char_traits<char> > (43B211h)
0043E5ED  add         esp,8
0043E5F0  mov         ecx,eax
0043E5F2  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (43A9D8h)
0043E5F7  mov         ecx,eax
0043E5F9  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (43B24Dh)
        cout << "CC::m_a=" << CC::m_a << endl;
0043E5FE  push        offset std::endl (43A7DAh)
0043E603  mov         eax,dword ptr [this]        C
0043E606  mov         ecx,dword ptr [eax+4]       D
0043E609  push        ecx  
0043E60A  push        offset string "CC::m_a=" (4B4234h)
0043E60F  push        offset std::cout (4CA068h)
0043E614  call        std::operator<<<std::char_traits<char> > (43B211h)
0043E619  add         esp,8
0043E61C  mov         ecx,eax
0043E61E  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (43A9D8h)
0043E623  mov         ecx,eax
0043E625  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (43B24Dh)
        cout << "CA::m_a=" << CA::m_a << endl;
0043E62A  push        offset std::endl (43A7DAh)
0043E62F  mov         eax,dword ptr [this]        E
0043E632  mov         ecx,dword ptr [eax]         F
0043E634  push        ecx  
0043E635  push        offset string "CA::m_a=" (4B4228h)
0043E63A  push        offset std::cout (4CA068h)
0043E63F  call        std::operator<<<std::char_traits<char> > (43B211h)
0043E644  add         esp,8
0043E647  mov         ecx,eax
0043E649  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (43A9D8h)
0043E64E  mov         ecx,eax
0043E650  call        std::basic_ostream<char,std::char_traits<char> >::operator<< (43B24Dh)

以上是我用vs2005EE反汇编的结果,当然只是显示Display函数中的内容,我在程序中标定了六处地方,分别用ABCDEF表示。A中将this地址,也就是CD的地址赋给eax,然后将eax中的内容送到ecx中然后输出,从堆砌的结果来看,应该是先堆砌CB(先继承CB),所以m_a位于偏移量为0的位置上,即this + 0的地址,然后再输出其值;D中是将this + 4的地址中的内容给了ecx后输出,4个字节刚好是一个int的大小,也就是m_a的大小,从堆砌上来看,CC中继承的m_a在DD的this + 4的位置上,符合堆砌的结果。最后,E、F跟输出CB时一致,说明编译器认为CA::m_a的地址和CB::m_a的地址一致。因为类中没有虚函数,所以没有虚函数的指针表,变量便按照继承的顺序堆砌。以上是我的理解,请大家指正。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-23 21:21

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表