samedi 27 août 2016

Connection of pure virtual signal of interface class

I want to connect some object's signals derived from an interface class. The connection is done in QWidget::listenToAnimal(AnimalInterface*). This does not work because qt_metacall is not a member of 'AnimalInterface' and static assertion failed: No Q_OBJECT in the class with the signal.

Of course AnimalInterface does not have the Q_OBJECT macro and does not inherit QObject because it is an interface...

I want to connect through the interface class because I do not want to manually retype the same code for Cat and for Dog.

Is it possible to connect the signal the way I want to? Perhaps with templates? Is this perhaps a lambda-specific problem?

header:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class AnimalInterface{
public:
    virtual ~AnimalInterface();

    virtual void makeSound() = 0;

/*signals*/
    virtual void madeSound() = 0;
};
Q_DECLARE_INTERFACE(AnimalInterface,"interface")



class Dog : public QObject, public AnimalInterface
{
    Q_OBJECT
    Q_INTERFACES(AnimalInterface)
public:
    void makeSound();
signals:
    void madeSound();
};


class Cat : public QObject, public AnimalInterface
{
    Q_OBJECT
    Q_INTERFACES(AnimalInterface)
public:
    void makeSound();
signals:
    void madeSound();
};



class Widget : public QWidget
{
    Q_OBJECT
    Cat *cat_;
    Dog *dog_;
public:
    Widget(QWidget *parent = 0);
    ~Widget();
    void listenToAnimal(AnimalInterface *animal);
};

#endif // WIDGET_H

cpp:

#include "widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    dog_ = new Dog;
    cat_ = new Cat;

    listenToAnimal(dog_);
    listenToAnimal(cat_);

    dog_->makeSound();
    cat_->makeSound();
}

void Widget::listenToAnimal(AnimalInterface *animal)
{
    connect(animal, &AnimalInterface::madeSound,
            this,
            [](){
                qDebug()<<"animal made sound";
            });
}

Widget::~Widget()
{

}


void Cat::makeSound()
{
    qDebug()<<"Cat says miaow";
    emit madeSound();
}
void Dog::makeSound()
{
    qDebug()<<"Dog says wuff";
    emit madeSound();
}

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

Aucun commentaire:

Enregistrer un commentaire