2009-12-27 2 views
4

должен я имею следующую иерархию классов:dynamic_cast возвращает NULL, но это не

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) 

    [...] 
} 

Я использую QT, и я пытаюсь создать плагин (для моего приложения) с QTPLUGIN. Я создаю экземпляр DASQLiteStorage и я даю этот экземпляр объекта ИЗНУТРИ плагина:

// 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); 
} 

Проблема заключается в том, что dynamic_cast возвращает мне нуль-указатель (не ожидал), при этом dynamic_cast в моем основном приложении (т.е. до «gateway-> setDefaultStorage (storage);») дает мне действительный указатель (ожидается).

Кто-нибудь знает, почему это может случиться? Работает ли программа в другом диапазоне памяти в качестве плагина? Может ли это привести к таким проблемам? Любые идеи, как это исправить?

Большое спасибо!


EDIT: Я пробовал некоторые предложения:

// 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; 
} 

В первой строке метода, s равно NULL, то во втором с содержит правильный указатель и третий - другой указатель. Почему эти указатели не равны?
И почему мог dynamic_cast быть до сих пор не работает, хотя я использую сейчас:

pluginLoader()->setLoadHints(QLibrary::ResolveAllSymbolsHint | QLibrary::ExportExternalSymbolsHint); 




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. 
    } 
} 

Эти ошибки сегментации не должны возникать, если они? Но почему они?

+0

Является ли класс 'DASQLiteStorage' определенным в вашем приложении? Я не уверен, что происходит в границах динамической нагрузки, если унаследованная связь известна только с одной стороны. –

+0

Является ли IStorage чистым виртуальным (например, интерфейсом), поскольку это имя подразумевает? что такое тип хранилища, когда код находится в 'gateway-> setDefaultStorage (хранилище);' –

+0

DASQLiteStorage определен в моем основном приложении. Как я писал в комментариях выше, хранилище имеет тип DASQLiteStorage. –

ответ

4

В принципе, RTTI ненадежен по границам модулей. Здесь у разных компиляторов другое поведение; вам придется исследовать, как ваш компилятор/версия действует в этом случае. Конечно, если у вас есть другой компилятор/версия для основного приложения и плагина, у него явно нет шансов на работу.

Использовать static_cast для работы.

+0

Когда я выполняю static_cast, он работает. Но в коде я получаю ошибку сегментации.Я не знаю, если это относится к этому вопросу ... Итак, динамическое_канирование в плагинах неэффективно и его следует избегать? –

+4

В общем, при работе с DLL и Qt-классами вы должны использовать 'qobject_cast' вместо' dynamic_cast'. Даже в документах QtPlugin вы можете найти, что вы должны использовать 'qobject_cast', чтобы определить, реализует ли плагин определенный интерфейс. –

+0

Использование статического приведения в присутствии множественного наследования вызовет всевозможные проблемы. Вы должны иметь возможность обнаруживать тип во время выполнения и выполнять соответствующий перевод. –

Смежные вопросы