dynamic_cast返回NULL,但不应

Säm*_*ämy 5 c++ plugins qt dynamic-cast

我具有以下类层次结构:

class IStorage {
    [...]
}
Q_DECLARE_INTERFACE(IStorage, "ch.gorrion.smssender.IStorage/1.0")


class ISQLiteStorage: public IStorage { 
    Q_INTERFACES(IStorage)

    [...] 
}
Q_DECLARE_INTERFACE(ISQLiteStorage, "ch.gorrion.smssender.ISQLiteStorage/1.0")


class DASQLiteStorage: public QObject, public ISQLiteStorage {
    Q_OBJECT
    Q_INTERFACES(ISQLiteStorage)

    [...]
}
Run Code Online (Sandbox Code Playgroud)

我正在使用QT,并尝试使用QtPlugin创建一个插件(针对我的应用)。我正在创建DASQLiteStorage的实例,并将此实例提供给插件中的FROM对象:

// the next line is within my main app.
// storage is the DASQLiteStorage instance.
// gateway is an object from within the plugin.
gateway->setDefaultStorage(storage);

// this method lies within the plugin
void AbstractGateway::setDefaultStorage(IStorage* storage) {
    defaultStorage_ = dynamic_cast<ISQLiteStorage*>(storage);
}
Run Code Online (Sandbox Code Playgroud)

问题是,dynamic_cast返回空指针(不是预期的),而在我的主应用程序中执行dynamic_cast时(即在“ gateway-> setDefaultStorage(storage);”之前)给了我有效的指针(预期)。

有谁知道为什么会这样?程序与插件在不同的内存范围内运行吗?这会导致此类问题吗?任何想法如何解决这一问题?

非常感谢!


编辑:我已经尝试了一些建议:

// this method lies within the plugin
void AbstractGateway::setDefaultStorage(IStorage* storage) {
    ISQLiteStorage* s = dynamic_cast<ISQLiteStorage*>(storage);
    s = static_cast<ISQLiteStorage*>(storage);
    s = qobject_cast<ISQLiteStorage*>((QObject*)storage);

    defaultStorage_ = s;
}
Run Code Online (Sandbox Code Playgroud)

在方法的第一行中,s等于NULL,在第二行中s包含正确的指针,在第三行中包含另一个指针。这些指针为什么不相等?
为什么我现在正在使用dynamic_cast仍不能正常工作:

pluginLoader()->setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint);
Run Code Online (Sandbox Code Playgroud)




EDIT2:我注意到,我在代码中得到的细分错误也与此相关。我有以下构造:

// The following classes are defined within the main app.
class ILoginAccount: public IAccount [...]

class AbstractAccountStroageOfficer {
public:
    AbstractAccountStroageOfficer(IAccount* account)[...]
}


// These classes are defined within my plugin and are created from within the plugin.
class BCAccount: public ILoginAccount {
public:
    BCAccount()
      : ILoginAccount(new DAAccountStorageOfficer(this))
    {};
}

class DAAccountStorageOfficer: public AbstractAccountStorageOfficer {
public:
    DAAccountStorageOfficer(ILoginAccount* account)
      : AbstractAccountStorageOfficer(account) // This line raises a segfault.
    {
        IAccount* a = account; // This line raises a segfault as well.
        a = dynamic_cast<IAccount*>(account); // This as well.
        a = static_cast<IAccount*>(account); // This as well.
    }
}
Run Code Online (Sandbox Code Playgroud)

这些分割错误不应该发生吗?但是为什么呢?

Ter*_*fey 4

基本上,RTTI 在跨模块边界时是不可靠的。不同的编译器在这里有不同的行为;您必须研究您的编译器/版本在这种情况下的行为。当然,如果您的主应用程序和插件有不同的编译器/版本,那么它显然没有机会工作。

使用 static_cast 作为解决方法。

  • 一般来说,在处理 DLL 和 Qt 类时,应该使用 `qobject_cast` 而不是 `dynamic_cast`。即使在 QtPlugin 文档中,您也可以发现应该使用“qobject_cast”来确定插件是否实现特定接口。 (4认同)