C++ 多继承 接口

FrankSun80 2010-01-04 06:06:49
以下代码输出:
funInIA
funInIA
为什么,
怎么样才能如我原来想的输出:
funInIA
funInIB
请知道的人帮我下,或者给个链接,谢谢~~

#include<iostream>
using namespace std;

struct IA
{
virtual void funInIA() = 0;
};

struct IB
{
virtual void funInIB() = 0;
};

struct C : public IA, public IB
{
virtual void funInIA()
{
cout << "funInIA" << endl;
}

virtual void funInIB()
{
cout << "funInIB" << endl;
}
};

int main()
{
IA* pIA = new C;
pIA->funInIA();

IB* pIB = (IB*)(void*)(pIA);
//IB* pIB = new C;
pIB->funInIB();

delete pIA;
return 0;
}
...全文
487 40 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
Meteor_Code 2010-01-06
  • 打赏
  • 举报
回复
你用SIZEOF测一下你的带有VIRTUAL方法的类大小
肯定比你定义的数据多4个字节,也就是一个指针的字节
这个指针就在每个类对象的最前面,它指向一个函数指针数组,数组里的每个函数指针就是按照你VIRTUAL方法定义的顺序排列下来的函数指针。你调用这些类的函数的时候全部转化为对这个数组中某个索引的调用。
IA* pIA = new C;
pIA->funInIA();

IB* pIB = (IB*)(void*)(pIA);
//IB* pIB = new C;
pIB->funInIB();
你把一个假的PA给了PB,结果pIB->funInIB();会调用pIB指向对象那个数组的索引为0的函数,正好是funInIA,所以就你看到的了。
如果你用隐式转换,编译其会帮你完成一些工作
但我个人认为,最好的转化是子类指针,转化为父类,这样可以在程序里使用一个假的父类实现各类子类的功能,但子类转化为父类是不安全的
traceless 2010-01-05
  • 打赏
  • 举报
回复
看一下com,或者去看一下directshow的例子源代码,可以设计更好的架构

那样强制了又强制,或者用共享指针,我认为都不好
FrankSun80 2010-01-05
  • 打赏
  • 举报
回复
刚试了一下,增加新的接口IAB好像不能解决这个问题。

[Quote=引用 23 楼 lxy4437 的回复:]
C/C++ codestruct IA {...};struct IB {...};struct IAB :public IA,public IB {/*do nothing here*/};struct C :public IAB {...};struct D :public IAB {...};
boost::shared_ptr<IAB> CreateInstance(void) {?-
[/Quote]
seagj 2010-01-05
  • 打赏
  • 举报
回复
昨晚刚看的com,没想到早上看到这贴,当复习了
flyerwing 2010-01-05
  • 打赏
  • 举报
回复
很晕很晕
ccixpg 2010-01-05
  • 打赏
  • 举报
回复
up 下
FrankSun80 2010-01-05
  • 打赏
  • 举报
回复
自己顶下~~
hhwei1985 2010-01-05
  • 打赏
  • 举报
回复
up
FrankSun80 2010-01-04
  • 打赏
  • 举报
回复
谢谢,真该回去好好看看了!
[Quote=引用 30 楼 sammylan 的回复:]
楼主看一下COM本质论吧,看前面几章即可
[/Quote]
FrankSun80 2010-01-04
  • 打赏
  • 举报
回复
是的,应该始终只有一个虚函数表吧,这时候好像函数的名字一点作用也没了?
能帮忙再描述详细点吗?
除了以上提到的:用dynamic_cast好像能转到正确的虚表上去,或者在类里实现接口之间的查询转换。


[Quote=引用 29 楼 meteor_code 的回复:]
虚函数表,碰到的正好是PA
[/Quote]
SammyLan 2010-01-04
  • 打赏
  • 举报
回复
楼主看一下COM本质论吧,看前面几章即可
Meteor_Code 2010-01-04
  • 打赏
  • 举报
回复
虚函数表,碰到的正好是PA
traceless 2010-01-04
  • 打赏
  • 举报
回复
可以好好借鉴com的思想
FrankSun80 2010-01-04
  • 打赏
  • 举报
回复
感觉好像Java,C#在这种情况下,不用这么麻烦吧~~
FrankSun80 2010-01-04
  • 打赏
  • 举报
回复
谢谢!
项目里的代码已经这样了,而且比这个例子要修改的地方多,暂时还不想重构,所以想用最简单最优雅的方案解决这个问题。


[Quote=引用 22 楼 traceless 的回复:]
虽然有进步,比前面好多了,但是好有好多地方还可以改进
比如:
C/C++ code#define IIDMgr 3void CreateInstance(int IID,void**ppv)
{do
{if (IIDMgr!= IID)break;
INameMgr*pIntf= NULL;
pIntf=new CNameMgr();if (NULL== pIntf)break;*ppv= pIntf;
}while (FALSE);
}
你之前的那样显得很怪,还有如果需要导出多个接口的化,加个管理接口,使得接口更清晰
[/Quote]
FrankSun80 2010-01-04
  • 打赏
  • 举报
回复
谢谢,这个返回共享指针,解决了内存可能的泄露问题。

[Quote=引用 23 楼 lxy4437 的回复:]
C/C++ codestruct IA {...};struct IB {...};struct IAB :public IA,public IB {/*do nothing here*/};struct C :public IAB {...};struct D :public IAB {...};
boost::shared_ptr<IAB> CreateInstance(void) {?-
[/Quote]
traceless 2010-01-04
  • 打赏
  • 举报
回复
struct INameMgr
{
public:
virtual void GetObject(int IID, void **ppv) = 0;
};

CNameMgr 是INameMgr的实现类,你可以在CNameMgr的构造函数里,new 出struct C的对象,但我更喜欢:
struct INameMgr
{
public:
virtual void InitModule(void) = 0; // 在这个函数里new出C
virtual void UninitModule(void) = 0; //看函数名就知道是什么意思了吧
virtual void GetObject(int IID, void **ppv) = 0;
};
lxy4437 2010-01-04
  • 打赏
  • 举报
回复

struct IA {...};
struct IB {...};
struct IAB : public IA, public IB {/*do nothing here*/};
struct C : public IAB {...};
struct D : public IAB {...};
boost::shared_ptr<IAB> CreateInstance(void) { return new C; }
int main(void)
{
boost::shared_ptr<IAB> pIAB= CreateInstance();
pIAB->funInIA();
pIAB->funInIB();

return 0;
}
traceless 2010-01-04
  • 打赏
  • 举报
回复
虽然有进步,比前面好多了,但是好有好多地方还可以改进
比如:
#define  IIDMgr 3
void CreateInstance(int IID, void **ppv)
{
do
{
if (IIDMgr != IID)
break;
INameMgr *pIntf = NULL;
pIntf = new CNameMgr();
if (NULL == pIntf)
break;
*ppv = pIntf;
} while (FALSE);
}

你之前的那样显得很怪,还有如果需要导出多个接口的化,加个管理接口,使得接口更清晰
ahao 2010-01-04
  • 打赏
  • 举报
回复
不错,就是这样
加载更多回复(20)

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧