2013-12-11 3 views
0

Я использую наблюдаемый наблюдаемый шаблон в моей программе. Все работало до того, как мне пришлось немного изменить код. Если быть точным, я изменил наследование класса IObserver - сейчас он наследует QObject:Множественное наследование QObject из-за доступа к методу deleteLater()

class IObserver : public QObject 
{ 
... 

Я сделал это потому, что только одна вещь - мне нужно deleteLater() метод, который будет использоваться в качестве наблюдателя, так что я бы быть в состоянии вызвать реализацию деинициализации виртуальных функций() IObserver. Таким образом, я мог стандартизировать каждый обработчик сообщений IObserver.

Проблема в том, что я уже унаследовал QObject (косвенно) в некоторых классах Observer. Как MainForm или AboutDialog. Все идет хорошо, пока я не попытаюсь вызвать метод «connect» в классе AboutDialog.

Что я могу сделать? Мне действительно нужен этот метод deleteLater(), поскольку я не могу использовать «delete this» в коде IObserver - это вызовет деструктор IObserver, а не классы MainForm или Storage.

спасибо.

+0

Возможно, некоторый намек здесь: [http://stackoverflow.com/questions/3259728/using-qt-signals-and-slots-with-multiple-inheritance](http://stackoverflow.com/questions/3259728/ using-qt-signals-and-slots-with-multiple-inheritance) – jbh

ответ

1

Мне действительно нужен этот метод deleteLater(), поскольку я не могу использовать «удалить это» в коде IObserver - это вызовет деструктор IObserver, а не классы MainForm или Storage, например.

Если вы сделаете свой деструктор виртуальным (и вы должны!), Он назовет производный деструктор просто отлично. Но проблема в том, что разрушение объекта во время обработки некоторого сигнала/слота может вызвать проблемы с циклом событий. В любом случае, вы должны быть очень осторожны с delete this.

Проблема в том, что я уже унаследовал QObject (косвенно) в некоторых классах Observer.

Одним из способов вы можете реализовать это, не уверен, что лучший мысли:

template <typename Derived> 
class IObserver 
{ 

    // Just to be sure: (C++11) 
    static_assert(is_base_of<Derived, QObject>::value, 
        "must inherit from QObject when using IObserver"); 

    void deleteMe() 
    { 
     QObject* thisObject = dynamic_cast<QObject*>(this); 
     // no need for check if thisObject equals null. static assert does this. 
     thisObject->deleteLater(); 
    } 

}; 

class MainForm : public IObserver<MainForm>, public QMainWindow 
{ 
    // ... 
}; 

Я считаю, что эта модель называется статический полиморфизм.

+0

** Если вы делаете свой деструктор виртуальным (и вы должны!) ** Я использую 'virtual void deinitialisation() = 0' в IObserver и считаю, что в реализованной версии все ресурсы будут выпущены, поэтому после вызова deinit Я хочу удалить объект. Спасибо за пример, я попробую это завтра. –

+0

Проблема в том, что кто-то решил «удалить anIObserverPointer», он не очистит ресурсы производного класса. Кроме того, почему бы не переместить код с 'deinitialization()' на '~ IObserver()'? Гораздо безопаснее. –

0

Abandon наследование QObject для IObserver. Вместо этого добавьте такой метод для интерфейса.

class IObserver : public QObject { 
public: 
    QObject *object() const = 0; 
... 

Тогда, если реализация интерфейса наследует QObject вы вернётесь this указатель из object() метода. Если реализация интерфейса не наследует QObject, вы можете просто вернуть указатель на некоторый простой объект QObject, который будет обрабатывать уничтожение этого объекта. Затем вы можете просто подключить deleteLater к объекту, который возвращается этим методом.

Off тему
Использование интерфейсов для наблюдения в Qt обычно является устаревшим, слоты и сигналы делают эту работу отлично, и это более гибкий подход.

+0

> работа отлично Не во всех случаях.Когда нужен каждый возможный сигнал для записи в журнале, необходимо подключить этот сигнал к функциям журнала, которые не стандартизированы. Вместо того, чтобы делать 20-30 функций в промежутке, я использую 3-параметрическую общую функцию (та же идея, что и окна «SendMessage»). Плюс я могу полностью удалить наблюдателей, не повредив приложение. Вместо вызова определенной функции, например profileManager.getProfilesList, я вызываю Send (OC_PROFILEMNGR, MC_GETPRFNAMES, & myStringList). Поэтому мне все равно, есть ли какая-либо функция, например getProfileList или даже если такой менеджер существует. –