以下是我的设置的一些伪代码:
class IMyClass { ... }; // pure virtual class
class CMyBaseClass { .... };
class CMyClass : public CMyBaseClass, public IMyClass { ... }
然后我收集了CMyBaseClass *。我有自定义RTTI,它允许我找出一个类是否实现给定的接口。所以我可以找到哪些对象有IMyClass实现。我的问题是我无法将其强制转换为该界面。我不想使用标准的RTTI和动态演员。
我正在考虑在我的自定义RTTI中存储一些指针差异,以便在一对类之间进行转换,但我还没有弄清楚让我开心的实现。
还有其他解决方案吗?
答案 0 :(得分:5)
好吧,如果你坚持不使用语言RTTI,你可以像旧的COM一样使用:使你的所有类或接口都来自以下界面:
class IMyCast // similar to IUnknown
{
public:
virtual void *CastTo(interfaceId_t id) = 0; //Similar to IUnknown::QueryInterface
};
现在在你的CMyClass中:
class CMyClass : public CMyBaseClass, public IMyClass
{
//...
void *CastTo(interfaceId_t id)
{
switch (id)
{
case IMyClass_id: //or whatever
return static_cast<IMyClass*>(this);
//...other cases
default:
throw std::bad_cast(); //or return NULL
}
}
};
然后在用户代码中:
CMyBaseClass *obj;
IMyClass *my = static_cast<IMyClass*>(obj->CastTo(IMyClass_id));
答案 1 :(得分:1)
您可能需要增加自定义RTTI;至少这是我在几乎相同的情况下所做的。我的解决方案不是使用指针差异,而是为必要的(类,接口)对实例化一个“脚轮”功能模板。它是这样的:
void* GetInterface<C, I>(void*)
函数,然后在interfaceId - &gt;中注册指向此函数的指针。 GetInterface-function map(属于C类)。此函数将其参数转换为C *,然后将C *转换为I *,最后返回void *。 (必须使用void *进行黑客攻击,以便所有这些函数具有相同的签名,因此它们可以存储在地图中。)this
对象的动态类的映射,根据I :: GetId()查找相应的caster函数,并调用它传递this
。