Использование сигналов Qt и слотов с множественным наследованием - PullRequest
9 голосов
/ 16 июля 2010

У меня есть класс (MyClass), который наследует большую часть своей функциональности от встроенного объекта Qt (QGraphicsTextItem). QGraphicsTextItem наследуется косвенно от QObject. MyClass также реализует интерфейс, MyInterface.

class MyClass : public QGraphicsTextItem, public MyInterface

Мне нужно иметь возможность использовать connect и disconnect на MyInterface*. Но похоже, что connect и disconnect работают только на QObject* экземплярах. Поскольку Qt не поддерживает множественное наследование от классов, производных от QObject, я не могу получить MyInterface из QObject. (В любом случае это не имеет большого смысла для интерфейса.)

В сети обсуждается проблема , но IMO предложенное решение в общем случае бесполезно (доступ к объекту через его интерфейс), поскольку вы не можете подключить сигналы и слоты с MyInterface* но должен привести его к производному типу. Так как MyClass является одним из многих MyInterface классов, полученных в результате, это потребовало бы "вонючего кода" операторов if-this-cast-to-this-else-if-cast-to-that и побеждать цель интерфейс.

Есть ли хорошее решение для этого ограничения?

ОБНОВЛЕНИЕ: Я заметил, что если я dynamic_cast a MyInterface* до QObject* (потому что я знаю все MyInterface -приобретенные классы также наследуются в конечном итоге от QObject, похоже, работает. То есть:

MyInterface *my_interface_instance = GetInstance();
connect(dynamic_cast<QObject*>(my_interface_instance), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot()));

Но это действительно похоже, что я прошу неопределенное поведение ....

Ответы [ 2 ]

12 голосов
/ 18 июля 2010

Вы сами нашли ответ: dynamic_cast работает так, как вы ожидаете.Это не неопределенное поведение.Если полученный вами экземпляр MyInterface не является QObject, приведение вернет ноль, и вы можете защититься от этого (этого не произойдет, поскольку вы сказали, что все экземпляры интерфейса также являются QObjects).Помните, однако, что вам нужно включить RTTI, чтобы он работал.

Я бы также предложил несколько других предложений:

  • Используйте Q_INTERFACES функция (это не только для плагинов).Тогда вы будете работать в терминах QObject и запрашивать MyInterface, используя qobject_cast, когда это действительно необходимо.Я не знаю вашей проблемы в деталях, но, поскольку вы знаете, что все экземпляры MyInterface также являются объектами QObject, это кажется наиболее разумным подходом.

  • Добавление абстрактного метода QObject* asQObject()в MyInterface и реализовать его как { return this; } во всех подклассах.

  • Имея QGraphicsTextItem (состав) вместо , являющийся единица (наследование).

7 голосов
/ 16 июля 2010

Вы можете объявить MyInterface, который принимает QObject в своем конструкторе:

class MyInterface {
public:
                MyInterface(QObject * object);
    QObject *   object() { return m_object; }
    ...
private:
    QObject *   m_object;
};

MyInterface::MyInterface(QObject * object) :
    m_object(object)
{
    ...
}

Затем в конструкторе MyClass:

MyClass::MyClass() :
MyInterface(this)
{
    ...
}

И вы можете подключить сигнал:

MyInterface *my_interface_instance = GetInstance();
connect(my_interface_instance->object(), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot()));
...