PDA

View Full Version : Why can't I inherit both QLineEdit and QPushButton to same class?



rawfool
11th May 2014, 19:45
Both QPushButton & QLineEdit are derived from QWidget. But I'm unable to inherit both on to a single class.
When I replicate the same kinda things using generic C++, it works. I'm unable to understand why this doesn't work the same way for Qt classes ?



// A - Base class
// P, Q - Derived classes from A
// Z - Derived from P, Q
// Works fine with this order.

#include <iostream>

using namespace std;

class A
{
public:
A() { cout << "A::Ctor\n"; }
~A() { cout << "A::Dtor\n"; }
};

class P : public A
{
public:
P() { cout << "P::Ctor\n"; }
~P() { cout << "P::Dtor\n"; }
};

class Q : public A
{
public:
Q() { cout << "Q::Ctor\n"; }
~Q() { cout << "Q::Dtor\n"; }
};

class Z : public P, public Q
{
public:
Z() { cout << "Z::Ctor\n"; }
~Z() { cout << "Z::Dtor\n"; }
};

int main(int argc, char *argv[])
{
Z obj;
return 0;
}

But the same kinda inheritance isn't working for Qt classes

#include <QApplication>
#include <QPushButton>
#include <QLineEdit>
#include <QDebug>

class SomeWidget : public QPushButton, public QLineEdit // Both derived from QWidget, which is derived from QObject
{
Q_OBJECT
public:
SomeWidget() { qDebug() << "SomeWidget::Ctor"; }
~SomeWidget() { qDebug() << "SomeWidget::Dtor"; }
};

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

SomeWidget wid;
wid.show();

return a.exec();
}

#include "main.moc"

Issues I got when I compiled this

Warning: Class SomeWidget inherits from two QObject subclasses QPushButton and QLineEdit. This is not supported!
Debug/main.moc:-1: In member function 'virtual const QMetaObject* SomeWidget::metaObject() const':
error: 'QObject' is an ambiguous base of 'SomeWidget'
error: 'QObject' is an ambiguous base of 'SomeWidget'

anda_skoa
11th May 2014, 19:56
This kind of diamond shaped derivation is almost never a good idea, even if it is supported by C++ in general.

It gets you into all kinds of ambiguous situations, e.g. if your class A has a virtual method and both P and Q implement it, which one of the two implementations is called when you call the method on Z?

In the case of QObject subclasses this kind of hierachy is made unavailable to make the QObject addons work properly, e.g. the code generated by MOC when it encounters classes with the Q_OBJECT marker, etc.

What is you actual use case?

Cheers,
_

rawfool
11th May 2014, 21:03
There's nothing aimed at. I was just trying to see what happens if I derive from both QPushButton & QLineEdit.
Thank you for giving me wisdom.

wysota
12th May 2014, 09:54
There's nothing aimed at. I was just trying to see what happens if I derive from both QPushButton & QLineEdit.
Thank you for giving me wisdom.

Usually to get rid of the diamond you can substitute inheritance with composition.

rawfool
12th May 2014, 10:31
Composition, do you mean like this - ?


class SomeWidget : public QLineEdit
{
Q_OBJECT
QPushButtton * clearButton;
public:
SomeWidget();
~SomeWidget();
....
private slots:
void onClearButton_Click(void);
...
};

Do you mean - Achieving all properties of widget by appropriately sub-classing required class(es) & using some class(es) as members ?

wysota
12th May 2014, 11:07
More likely:


class Widget : public QWidget {
public:
Widget(QWidget *parent = 0) : QWidget(parent) {
m_lineEdit = ...;
m_pushButton = ...;
QLayout *l = ....
l->addWidget(m_lineEdit);
l->addWidget(m_pushButton);
}

QLineEdit *lineEdit() const { return m_lineEdit; }
QPushButton* pushButton() const { return m_pushButton; }
private:
QLineEdit *m_lineEdit = 0;
QPushButton *m_pushButton = 0;
};