免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3412 | 回复: 14
打印 上一主题 下一主题

[C++] 请问个C++中多重继承的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-04-23 08:33 |只看该作者 |正序浏览
我在看COM时,发现每个接口都是从IUnknown继承来的,
该接口都有QueryInterface虚函数,那么最后COM类中
的每个vtable中都要实现该函数,我现在模拟了个:
class IA
{
public:
   virtual void dsp()=0;
};


class B:public IA
{
public:
    virtual void dsp()=0;
};

class C:public IA
{
public:
    virtual void dsp()=0;
};


class cls:public B,public C
{
public:
        void dsp(){printf("I dont know\n");}
};
可是最后类cls只实现了一个dsp函数,那么该函数
到底是属于class B还是class C中的dsp函数?
还是说这两个函数都指向同一个地方呢?
能说说理由吗?

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
15 [报告]
发表于 2013-04-23 18:25 |只看该作者
又研究语言了, 表示不懂.

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
14 [报告]
发表于 2013-04-23 13:48 |只看该作者
本帖最后由 w_anthony 于 2013-04-23 13:50 编辑
netdoger 发表于 2013-04-23 11:54
一、实现的当然是cls中的,本类只实现本类的,怎么能实现别的类的。
===================
问题是:cl ...


经过VC实际测试和反汇编研究是这样的。
void func(cls* p) { p->dsp(); }
void func2(B* p) { p->dsp(); }
void func3(C* p) { p->dsp(); }
void func4(IA* p) { p->dsp(); }
cls n;
func(&n);    //编译OK
func2(&n);  //编译OK
func3(&n);  //编译OK
func4(&n);  //编译ERROR
DEBUG版编译(RELEASE优化会面目全非不好分析):
1、func中直接取虚表(标记为1号)中的dsp并调用之
2、&n转换为B*无偏移,func2内直接取虚表(是1号虚表)中的dsp并调用之
3、&n转换为C*有偏移,func3内形式上也是直接取虚表,但因为转C*时有偏移,此处根据C*取虚表实际上是另外一个虚表(标记为2号),取其中的dsp并调用之,但实际上调用到的函数是“[thunk]:cls::dsp`adjustor{4}”,它会对C*作反偏移回到cls*,再跳入真正的dsp中。
4、编译错误,因为有歧义,如果用func4((B*)&n)或者func4((C*)&n)这样,那就没有什么好说的了。

如果要说cls n,n.dsp究竟会调用谁的dsp,那肯定是cls它自己的dsp,但是如果说通过谁的虚表找到的dsp,那应该是排前面继承的那个虚表找到的。但实际上无论通过哪个虚表找到的都是同一个函数,所以也没什么歧义的问题。





论坛徽章:
0
13 [报告]
发表于 2013-04-23 12:26 |只看该作者
littledick 发表于 2013-04-23 12:21
而且这个设计本身就有问题。共性的内容应该上升为基类,拥有特性的才做子类。如果出现楼主的这种设计, ...


同意

论坛徽章:
6
技术图书徽章
日期:2013-11-13 11:11:27子鼠
日期:2014-02-20 17:54:13处女座
日期:2014-06-16 17:43:33午马
日期:2014-08-08 09:11:17未羊
日期:2014-08-10 11:57:072015年辞旧岁徽章
日期:2015-03-03 16:54:15
12 [报告]
发表于 2013-04-23 12:21 |只看该作者
windoze 发表于 2013-04-23 10:27
就这个例子而言,只要你不通过IA*去调用cls实例中的dsp,不会有什么问题,比如:不过还是强烈建议你仔细看看 ...


而且这个设计本身就有问题。共性的内容应该上升为基类,拥有特性的才做子类。如果出现楼主的这种设计,绝对要推倒重构。

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
11 [报告]
发表于 2013-04-23 12:10 |只看该作者
回复 10# netdoger

继承有接口继承和实现继承:base class里纯虚函数,derived class里继承的是接口,也就是说,基类里声明有这个函数,可以用,但是实现是derived class的事情,
所以你的cls实现的就是cls的,你说不知道实现的“是谁的”,这说法根本不存在。如果base class实现了接口,derived class没有重写覆盖,那就是实现继承。

要想说“是谁的”,你得研究“调用的是谁的”,比如你可以试试 cls obj; obj.B::dsp(); 这样会报无法解析,因为cls实现的是cls自己的,B::dsp()接口没实现。

继承函数的调用,有多态调用和非多态调用:用指针或引用调用的以多态形式,即通过vtable查找函数;否则就是调用相应类的。cls obj;obj.dsp();就是调用cls的。

论坛徽章:
0
10 [报告]
发表于 2013-04-23 11:54 |只看该作者
cokeboL 发表于 2013-04-23 10:32
实现的当然是cls中的,本类只实现本类的,怎么能实现别的类的。

只能说是这个接口继承自哪个,B和C都是继 ...


一、实现的当然是cls中的,本类只实现本类的,怎么能实现别的类的。
===================
问题是:clsl类中有两个vtable中都有函数dsp,一个来自B类,一个来自C类,
所以我才不知道cls中实现的是哪个类中的dsp函数?

二、只能说是这个接口继承自哪个,B和C都是继承了IA的dsp()纯虚接口,cls实现了,那么通过B、C的指针或引用都可以
对cls中的dsp()接口进行调用
=================
那么如果是cls obj;
obj.dsp()是哪个vtable中的函数呢?因为cls类中有两张vtable表,如果说它们指向同一个地址,我想知道这里面的原因?

论坛徽章:
0
9 [报告]
发表于 2013-04-23 11:01 |只看该作者
本帖最后由 sonicling 于 2013-04-23 11:04 编辑

B和C中的dsp就是IA的dsp,只不过BC可能应该实现它,但是它们把实现dsp的责任推给了cls。这个dsp还是IA的dsp,BC中的纯虚dsp写不写都一样。

如果你把BC的dsp都换成另外一个名字,比如dsp1,才会引发你所问的问题。COM中一般不存在这种情况,COM中任意两个接口不存在同名虚函数 (可能有,但使用有限制)。

论坛徽章:
0
8 [报告]
发表于 2013-04-23 10:41 |只看该作者
w_anthony 发表于 2013-04-23 10:15
目前的编译器的实现机制是通过查询虚函数表来得到真实的函数入口地址,LZ这种情况下,两个类的虚函数表中ds ...

为什么说两个类的虚函数表中dsp都将指向同一个入口地址?能具体说说吗?

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
7 [报告]
发表于 2013-04-23 10:32 |只看该作者
本帖最后由 cokeboL 于 2013-04-23 10:56 编辑

实现的当然是cls中的,本类只实现本类的,怎么能实现别的类的。

只能说是这个接口继承自哪个,B和C都是继承了IA的dsp()纯虚接口,cls实现了,那么通过B、C的指针或引用都可以
对cls中的dsp()接口进行调用。
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP