【问题标题】:C++ casting a base pointer to an interface pointerC++ 将基指针转换为接口指针
【发布时间】:2011-08-04 07:35:32
【问题描述】:

这是我设置的一些伪代码:

class IMyClass { ... }; // pure virtual class
class CMyBaseClass { .... };
class CMyClass : public CMyBaseClass, public IMyClass { ... }

然后我收集了 CMyBaseClass*。我有自定义的 RTTI,可以让我找出一个类是否实现了给定的接口。所以我可以找到哪些对象具有 IMyClass 实现。我的问题是我无法将其转换为该界面。我不想使用标准 RTTI 和动态转换。

我正在考虑在我的自定义 RTTI 中存储一些指针差异,以便在一对类之间进行转换,但我还没有找到让我满意的实现。

还有其他解决方案吗?

【问题讨论】:

  • 不要认为有任何其他解决方案,因为知道如何投射纯粹是 RTTI 的责任,因为你必须先投射到正确的CMyClass*(或另一个后代)然后“返回" 到实际界面。
  • “自定义 RTTI”是什么意思?为什么不想使用“标准 RTTI”来解决这个问题?执行动态铸造的需要通常意味着设计问题;你确定你想不出更优雅(即多态)的架构吗?
  • 您为什么不想使用语言 RTTI?由于您使用的是接口,这意味着您已经拥有虚拟功能,因此您并没有真正避免标准 RTTI...如果您解释您不想要 RTTI 的哪些部分以及为什么,您可能会得到一些解决方案。
  • 嗯...我真的需要自定义 RTTI。通过使用我自己的实现,我有自动序列化/反序列化、与脚本语言绑定、一些调试工具等。如果我已经拥有自己的语言,我不应该使用 RTTI 语言,它可以为我提供所有信息除了找出 vtable 之外的层次结构。我也可以添加对这个演员表的支持,但我对我的解决方案并不着迷,所以我想我错过了一些简单的东西。

标签: c++ casting rtti


【解决方案1】:

好吧,如果你坚持不使用语言 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));

【讨论】:

  • static_cast 如何在编译器中发挥它的魔力?抱歉,我知道与该问题没有直接关系,但来到这里寻找答案是因为我想更好地理解 QueryInterface()。谢谢。
  • @Sabuncu:嗯,对于static_cast&lt;&gt;,源类型和目标类型在编译时都是已知的,所以转换只是类型的改变和可能的固定偏移量。编译器只为每种类型保留一个表,其中包含每种基本类型的偏移量。
【解决方案2】:

您可能需要增强您的自定义 RTTI;至少这是我在几乎相同的情况下所做的。我的解决方案不是使用指针差异,而是为必要的(类、接口)对实例化一个“施法者”函数模板。是这样的:

  • 所有接口都有一个唯一的 int id。为此,需要从 InterfaceBase 派生 MyInterface。 id 在第一次 MyInterface::GetId() 调用时自动分配。
  • MyClass 的实现者(实现 MyInterface)需要在 .cpp 文件中添加一个 IMPLEMENTS(MyClass, MyInterface) 宏。
  • 宏实例化void* GetInterface&lt;C, I&gt;(void*) 函数,然后在 interfaceId -> GetInterface-function 映射(属于 C 类)中注册指向该函数的指针。此函数将其参数转换为 C*,然后将 C* 转换为 I*,最后返回 void*。 (使用 void* 进行黑客攻击是必要的,这样所有这些函数都具有相同的签名,因此它们可以存储在地图中。)
  • 要获得一个接口,用户需要调用一个myObject->GetInterface() 函数,在CMyBaseClass 中实现。它找到属于this 对象的动态类的映射,根据I::GetId() 查找适当的caster 函数,并通过this 调用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    相关资源
    最近更新 更多