C++多继承之基类直接互相转化.

antimatterworld 2009-05-19 10:53:29
C++多继承的特点比较复杂。
有个未知的类,此类继承自N多基类,我们只对这些基类有所了解,但是不知道此类的结构信息,更不知道此类的类名。
现有一个指向此类实例的基类型指针,我们想通过转化,得到指向此类实例的其他基类型指针。
问:此类如何实现,以及用户该如何实现类型转化。
这个问题把俺难住了,研究了一下,有所收获,拿出来挣点技术分。


#include <iostream>
using namespace std;

class IUnknow
{
public:
virtual void QueryInterface()=0;
virtual void* Convert()=0;
};

class ISomeInterface:public IUnknow
{
public:
virtual void SomeFunction()=0;
};

class INondelegatingUnknow
{
public:
virtual void NondelegatingQueryInterface()=0;
virtual void* NondelegatingConvert()=0;
};

class CObj:public ISomeInterface,public INondelegatingUnknow
{
public:
void QueryInterface()
{
cout << "this*PtrAddress:" << this << endl;
cout << "QueryInterface()" << endl;
}
void* Convert()
{
cout << "this*PtrAddress:" << this << endl;
return (INondelegatingUnknow*)this;
}
void SomeFunction()
{
cout << "this*PtrAddress:" << this << endl;
cout << "SomeFunction()" << endl;
}
void NondelegatingQueryInterface()
{
cout << "this*PtrAddress:" << this << endl;
cout << "NondelegatingQueryInterface()" << endl;
}
void* NondelegatingConvert()
{
cout << "this*PtrAddress:" << this << endl;
return (IUnknow*)this;
}

};

void Display(CObj* po)
{

}

int main()
{
CObj* pobj = new CObj;
////////////////////////////
INondelegatingUnknow* pnondelegatingUnknow = (INondelegatingUnknow*)pobj;
IUnknow* punknow = (IUnknow*)pobj;
cout << "TipInfo:INondelegatingUnknow*->NondelegatingQueryInterface()" << endl;
pnondelegatingUnknow->NondelegatingQueryInterface();
cout << "TipInfo:Ptr Address:" << pnondelegatingUnknow << endl;
///////////////////////////
cout << "TipInfo:IUnknow*->QueryInterface()" << endl;
punknow->QueryInterface();
cout << "TipInfo:Ptr Address:" << punknow << endl;
///////////////////////////
cout << "TipInfo:--------------------------------------------------" << endl;
///////////////////////////
cout << "TipInfo:(IUnknow*)INondelegatingUnknow*\tWe call QueryInterface(),but..." << endl;
punknow = (IUnknow*)pnondelegatingUnknow;//punknow Value Change
punknow->QueryInterface();
cout << "TipInfo:Ptr Address:" << punknow << endl;
///////////////////////////
cout << "TipInfo:(ISomeInterface*)(IUnknow*)INondelegatingUnknow*" << endl;
ISomeInterface* psomeinterface = (ISomeInterface*)punknow;//punknow from INondelegatingUnknow*
//psomeinterface->SomeFunction();//Exception! Cannot execute from INondelegatingUnknow* to IUnknow* to ISomeInterface*
cout << "TipInfo:Ptr Address:" << psomeinterface << endl;
///////////////////////////
cout << "TipInfo:(INondelegatingUnknow*)IUnknow*\tWe call NondelegatingQueryInterface()" << endl;
punknow = (IUnknow*)pobj;
pnondelegatingUnknow = (INondelegatingUnknow*)punknow;
pnondelegatingUnknow->NondelegatingQueryInterface();
cout << "TipInfo:Ptr Address:" << pnondelegatingUnknow<< endl;
//////////////////////////
cout << "TipInfo:(INondelegatingUnknow*)ISomeInterface*\tWe call NondelegatingQueryInterface(),but..." << endl;
psomeinterface = (ISomeInterface*)pobj;
pnondelegatingUnknow = (INondelegatingUnknow*)psomeinterface;
pnondelegatingUnknow->NondelegatingQueryInterface();
cout << "TipInfo:Ptr Address:" << pnondelegatingUnknow << endl;
/////////////////////////
cout << "TipInfo:--------------------------------------------------" << endl;
/////////////////////////
cout << "TipInfo:INondelegatingUnknow* PtrAddress" << endl;
pnondelegatingUnknow = (INondelegatingUnknow*)pobj;
cout << pnondelegatingUnknow << endl;
cout << "TipInfo:ISomeInterface* PtrAddress" << endl;
psomeinterface = (ISomeInterface*)pobj;
cout << psomeinterface << endl;
cout << "TipInfo:IUnknow* PtrAddress" << endl;
punknow = (IUnknow*)pobj;
cout << punknow << endl;
/////////////////////////
cout << "TipInfo:__________________Convert Function_______________" << endl;
cout << "TipInfo:INondelegatingUnknow*->NondelegatingConvert() to IUnknow*,We call QueryInterface()" << endl;
punknow = (IUnknow*)pnondelegatingUnknow->NondelegatingConvert();
punknow->QueryInterface();
cout << "TipInfo:Ptr Address:" << punknow << endl;
/////////////////////////
cout << "TipInfo:(ISomeInterface*)(IUnknow*)INondelegatingUnknow*->NondelegatingConvert(),We call SomeFunction" << endl;
psomeinterface = (ISomeInterface*)punknow;
psomeinterface->SomeFunction();
cout << "TipInfo:Ptr Address:" << psomeinterface << endl;
/////////////////////////
cout << "TipInfo:IUnknow*->Convert() to INondelegatingUnknow*,We call NondelegatingQueryInterface()" << endl;
punknow = (IUnknow*)pobj;
pnondelegatingUnknow = (INondelegatingUnknow*)punknow->Convert();
pnondelegatingUnknow->NondelegatingQueryInterface();
cout << "TipInfo:Ptr Address:" << pnondelegatingUnknow << endl;
return 0;
}
...全文
297 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
pengzhixi 2009-05-19
  • 打赏
  • 举报
回复
学习
arong1234 2009-05-19
  • 打赏
  • 举报
回复
假如你的派生类是一个未知的类,你就不应该假定这个类有其他基类,也不该假定这个类能从某个基类A合法的转到另外一个基类B,因为对于A来说,B根本是不存在的,只有你知道派生类才能知道是否有这么个B。因此无论这个能否做到,你应该都努力避免去这么做。

因此解决这个问题最关键的是不要假定那个派生类是未知的,你应该把你的切换基类的需求交给你派生类来做,只有它知道所有的事实。

方法基本有:
1。学习.net,用reflector查询类信息,了解它派生类到底有哪些基类
2。学习COM,所有基类都实现一个共同的虚函数,这个虚函数允许查询其他基类

另外一个建议就是:多基类一般都是不建议的,除非你已经建立起类似于COM的标准用法,千万不要随便用多继承
giscn 2009-05-19
  • 打赏
  • 举报
回复
上述代码中:很多强制转换是不必要的,形成习惯之后反而容易引入很多bug, 使用强制转换的地方要特别小心,
另外,测试代码最好试着访问基类的变量,否则一些bug 因为C++编译器的处理会给掩盖起来
giscn 2009-05-19
  • 打赏
  • 举报
回复
dynamic_cast大致就是这个用法,已知object的一个基类的指针,想得到另外一个基类的指针。不过dynamic_cast比较慢,比C# as 慢很多,不可滥用
antimatterworld 2009-05-19
  • 打赏
  • 举报
回复
以前想找点dynamic_cast文档,一直没找到,后来也就没再过问,刚才实验了一下,发现dynamic_cast是这么用的

不知道大侠是否还有更多的信息给指点一下...
giscn 2009-05-19
  • 打赏
  • 举报
回复
通过子类的指针得到基类的指针,C++编译器会自动转换,但是如果只知道该类的一个基类的指针,想得到另外一个基类的指针,不用 dynamic_cast 是不行的
antimatterworld 2009-05-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 taodm 的回复:]
呃,竟然dynamic_cast都没跑龙套的机会?
[/Quote]
本打算使用dynamic_cast,后来发现用this直接转化比dynamic_cast字母少很多...
taodm 2009-05-19
  • 打赏
  • 举报
回复
呃,竟然dynamic_cast都没跑龙套的机会?
giscn 2009-05-19
  • 打赏
  • 举报
回复
除非做COM开发,COM 的QueryInterface不值得效法,太烦,完全是自己变换指针,dynamic_cast在实际中用的不是很多
scott_2009 2009-05-19
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 arong1234 的回复:]
假如你的派生类是一个未知的类,你就不应该假定这个类有其他基类,也不该假定这个类能从某个基类A合法的转到另外一个基类B,因为对于A来说,B根本是不存在的,只有你知道派生类才能知道是否有这么个B。因此无论这个能否做到,你应该都努力避免去这么做。

因此解决这个问题最关键的是不要假定那个派生类是未知的,你应该把你的切换基类的需求交给你派生类来做,只有它知道所有的事实。

方法基本有:
1。学习.net,用refl…
[/Quote]
com组建的接口转换
下载代码方式:https://pan.quark.cn/s/dd3561eca308 在软件开发领域,面向对象编程(OOP)是一种普遍采纳的结构化方法,它使得开发者能够借助模拟现实环境中的实体和关系来构建软件系统。在本案例中,我们观察到的是一个关于借助抽象类来执行不同几何图形面积求解的实践应用。现在,让我们详细分析这一议题。 标题 "应用抽象类计算面积" 清晰地表明我们将要讨论一个抽象类,此类设定了一个用于测量图形面积的标准函数,但并未提供实际的执行过程。抽象类在诸如C#或Java等编程语言中通常借助`abstract`修饰符进行声明,它们无法直接创建对象实例,仅能作为其他类的基础模板。 描述部分提及的"图形界面应用"暗示这是一个基于视觉用户界面(GUI)的系统,可能运用了.NET Framework的Windows Forms或WPF技术,或者是Java平台的Swing或JavaFX框架。在这样环境下,用户能够通过视觉元素与这些几何体进行互动,例如输入相关尺寸并观看到计算得出的面积值。 抽象类“几何体”内嵌了“计算面积”这一抽象函数。在代码层面,这可以被表述为: ```csharp public abstract class GeometricShape { public abstract double CalculateArea(); } ``` 随后,有三个派生类:圆(Circle)、矩形(Rectangle)和三角形(Triangle),它们各自提供了这个抽象函数的具体实现。比如,圆的面积是通过π乘以半径的平方得到的,矩形的面积是长和宽的乘积,而三角形的面积可能是底乘以高再除以2的结果。这些类将提供具体实现来计算它们各自的面积: ```csharp p...
内容概要:本文系统研究了移相控制全桥LLC谐振变换器的工作特性,深入分析其在不同工作模式下的运行机理与性能表现,重点探讨了软开关实现、高效率能量转换及宽范围电压调节等关键技术优势。通过Simulink搭建精确的仿真模型,对谐振腔参数、开关频率、电压增益、系统效率等关键指标进行仿真分析,验证了理论设计的正确性。同时,详细研究了移相控制策略对系统动态响应、稳定性和轻载/重载工况适应性的影响,揭示了控制参数与电路参数之间的耦合关系,为高频高效电源设计提供了理论依据和实践指导。; 适合人群:具备电力电子技术、模拟电路及自动控制理论基础,从事开关电源、新能源变换器、电动汽车充电模块或高频电源系统研发的工程师及高校研究生。; 使用场景及目标:①掌握全桥LLC谐振变换器的拓扑结构、工作原理与关键参数设计方法;②理解移相控制在实现零电压开通(ZVS)和零电流关断(ZCS)中的作用机制;③通过Simulink仿真掌握变换器建模、参数优化与性能评估流程,服务于实际产品开发与学术课题研究。; 阅读建议:建议读者结合提供的Simulink仿真模型进行同步操作,重点关注谐振网络(Lr, Lm, Cr)参数与移相角之间的匹配设计,深入理解软开关条件的形成过程,并通过调整负载和输入电压进行多工况仿真,以全面掌握系统动态特性。

65,211

社区成员

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

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