PDA

View Full Version : Multiple inheritance question



marcvanriet
4th October 2010, 00:13
Hi,

I'm writing some classes to handle text that is transmitted over a serial communication link. There will be classes to 'observe' what is passing over the link. They are like textedits or linedits that show the data as it is received. Other classes will do logging etc.

I defined a base class for the observers with the necessary slots for receiving data. Then I derived a QUI object from this, based on a QPlainTextEdit. Like this :


class CComLineObserver : public QObject
{
Q_OBJECT
public:
explicit CComLineObserver(QObject *parent = 0);

public slots:
virtual void OnTxLine( QString sLine );
virtual void OnRxLine( QString sLine );
virtual void OnRxChar( QString sLine );

};

class CComLineTextEdit : public QPlainTextEdit, virtual public CComLineObserver
{
Q_OBJECT
public:
explicit CComLineTextEdit( QWidget * parent = 0 );

public slots:
virtual void OnRxLine( QString sLine );
};

When I use this CComLineTextEdit in a form, I get the following error message in setupUI of the UI_....H file that moc builds (teLog is the name of the gui object) :


ambiguous acces of 'setObjectName'
teLog->setObjectName(QString::fromUtf8("teLog"));

I think it has to do with the fact that both QPlainTextEdit and CComLineTextEdit are derived from QObject (the 'diamond problem'). I already used the 'virtual' keyword before 'CComLineTextEdit', but this doesn't help. I'm sure it's just a little syntax problem, but I just can't put my finger on it.

Does anyone know the solution ?

Thanks,
Marc

nish
4th October 2010, 06:21
According to the Qt docs, you can only derive from QObject once. Thats a hardcore rule u must follow in Qt.

marcvanriet
4th October 2010, 09:39
Really ??

I found an article now in the QQ : Academic Solutions to Academic Problems (http://doc.trolltech.com/qq/qq15-academic.html).

So we have a great toolkit with the great mechanism of signal and slots, but when I want to implement a common thing like an observer, I cannot use this mechanism ?

That is very disappointing. The workaround mentioned in QQ15 to have a wrapper member object is really really overengineered for most things I use. Maybe a todo for Trolltech : "allow a STRAIGHTFORWARD way to define interfaces that use the signal and slot mechanism".

Best regards,
Marc

ChrisW67
4th October 2010, 09:50
There's no real reason for CComListener to be a QObject if it is just an abstract interface. The public functions in the interface class can be treated as slots in the derived class For example, this seems to work:


#include <QtGui>
#include <QDebug>

// Class is abstract by virtue of having at least one pure virtual
class IComLineObserver
{
public:
explicit IComLineObserver() {}
virtual ~IComLineObserver() = 0;

// these can be slots in derived classes
virtual void OnTxLine( QString sLine ) {}
virtual void OnRxLine( QString sLine ) {}
virtual void OnRxChar( QString sLine ) {}
virtual void test() {}
};
IComLineObserver::~IComLineObserver() {}; // must have an implementation

class A: public QObject, public IComLineObserver
{
Q_OBJECT
public:
A() { }
~A() { }
public slots:
void test() { qDebug() << "Test"; }
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

A a;
QTimer t;
QObject::connect(&t, SIGNAL(timeout()), &a, SLOT(test()));
t.start(1000);
return app.exec();
}
#include "main.moc"

marcvanriet
4th October 2010, 10:30
Hi ChrisW67,

Well, CComListener wouldn't be purely abstract. I would like to put some basic functionality in it like connecting to a serial port object and handling stuff when a port is opened / closed / deleted / .... Some of this 'stuff' involves responding to signals of the serial port object.

But your suggestion leads me to a viable option : I could put the interface in an abstract class as you said, and define a member that is a QObject. This member could then interface to the serial port object and use callbacks to CComListener when it receives a signal from the serial port object. I'll give it a try.

Thanks,
Marc

P.S. Still, it would be great if it just worked plain and simple with signals and slots in the interface definition.