【问题标题】:reinterpret_cast to QObject's sublingreinterpret_cast 到 QObject 兄弟
【发布时间】:2013-01-22 13:37:50
【问题描述】:

我有某种对象工厂(基于模板),它非常适合我的目的。但现在我尝试使用派生自 QObject 和纯抽象类(接口)的类,但我遇到了奇怪的运行时错误。

这里是这个类的简单图(Derived)

class Interface  {
public:
    Interface(){}
    virtual ~Interface(){}    
    virtual int getResult() = 0;
};

class Derived : public QObject, public Interface {
    Q_OBJECT
public:
    explicit Derived(QObject *parent = 0);        
    int getResult();        
}; 

及其在derived.cpp中的实现:

#include "derived.h"    
Derived::Derived(QObject *parent)
    : QObject(parent) {
}    
int Derived::getResult() {
    return 55;
}

当我尝试将 void 指针强制转换为接口时,我会得到意外的(对我而言)行为,它可能是运行时错误,或其他方法调用(取决于类的大小)。

#include "derived.h"    
void * create() {
    return new Derived();
}

int main(int argc, char *argv[]) {
    Interface * interface = reinterpret_cast<Interface *>(create());    
    int res = interface->getResult(); // Run-time error, or other method is called here
    return 0;
}

你能解释一下为什么我不能将 void 指针转换为接口吗?有什么解决方法吗?

感谢您的回复

【问题讨论】:

  • reinterpret_cast?你试过dynamic_cast吗?
  • 我不能使用dynamic_castvoid*,因为void* 中没有RTTI。 (由于模板,我的工厂总是返回 void* 并将其转换为所需的模板类型,所以我必须使用 void* - 这种方法有大量遗留代码。)

标签: c++ qobject reinterpret-cast


【解决方案1】:

将指向派生类的指针重新解释为指向基类的指针会产生未定义的行为。多重继承突出了这一点:由于存在多个基类,并且两个基子对象必须具有不同的地址,因此它们不能具有与派生对象相同的地址。所以create 函数返回的指针指向Derived,但不一定指向Interface 子对象。它可以指向QObject 子对象,也可以都不指向。

最好的选择是从你的函数中返回Derived*Interface*;如果出于某种原因它必须是void*,那么您可以进行的唯一明确定义的转换是回到Derived*,然后可以使用标准转换将其转换为Interface*

通过使用void*,你已经抛弃了类型的所有静态和动态知识;恢复该信息的唯一方法是转换回正确的类型。

【讨论】:

  • 好的,我知道了。当我尝试使用来自void* 的残酷强制转换和多重继承时,这是我的错。谢谢!
【解决方案2】:

reinterpret_cast 与多重继承混合可能会导致各种问题。在您的情况下,void* 可能会指向DerivedQObject 部分,而不是Interface 部分。

使用dynamic_cast 可能会更好,它可以调整指针以指向派生类的正确子对象。

【讨论】:

    【解决方案3】:

    请注意,一般来说,需要这些类型的演员表是糟糕设计的标志。在您的特定情况下,您的工厂函数需要返回一个Interface*void* 在不涉及 C 接口的 C++ 中是不必要且不好的。

    除此之外,工厂函数是 Java 的东西,只有在应用严格的设计方法时才需要,这通常会比贡献干净和无错误的代码添加更多的绒毛。

    如果还是不行,你会想要dynamic_cast。在 Qt for QObjects 中,您可以查看 qobject_cast 在您的情况下是否有任何优点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-06
      • 1970-01-01
      • 2016-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多