Russian Qt Forum

Qt => Общие вопросы => Тема начата: Alf от Сентябрь 28, 2011, 12:58



Название: Виртуальное наследование от класса Qt
Отправлено: Alf от Сентябрь 28, 2011, 12:58
Код
C++ (Qt)
class A : public QObject {...};
class B : public A, public QWidget {...};

При попытке использовать в реализации класса 'B' указатель на объект базового класса 'QObject' возникает неоднозначность, предок какого из классов (QWidget или A) должен быть использован ? Очевидно, необходимо виртуальное наследование.

Код
C++ (Qt)
class A : public virtual QObject {...};
Но как быть с QWidget ?



Название: Re: Виртуальное наследование от класса Qt
Отправлено: GreatSnake от Сентябрь 28, 2011, 13:11
Цитировать
Но как быть с QWidget ?
Никак  :( В Qt не позволительно множественное наследование от QObject.


Название: Re: Виртуальное наследование от класса Qt
Отправлено: andrew.k от Сентябрь 28, 2011, 13:18
Цитировать
Но как быть с QWidget ?
Никак  :( В Qt не позволительно множественное наследование от QObject.
а почему?
И где это написано?


Название: Re: Виртуальное наследование от класса Qt
Отправлено: GreatSnake от Сентябрь 28, 2011, 13:25
Ну, хотя бы здесь (http://www.developer.nokia.com/Community/Wiki/%D0%91%D0%B0%D0%B7%D0%BE%D0%B2%D1%8B%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%81_QObject).


Название: Re: Виртуальное наследование от класса Qt
Отправлено: Igors от Сентябрь 28, 2011, 13:47
Ну, хотя бы здесь (http://www.developer.nokia.com/Community/Wiki/%D0%91%D0%B0%D0%B7%D0%BE%D0%B2%D1%8B%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%81_QObject).
Ну там не написано что нельзя  :) Можно, но просто это ничего хорошего не дает. т.к. QObject не есть виртуальный базовый класс для QWidget и др


Название: Re: Виртуальное наследование от класса Qt
Отправлено: Авварон от Сентябрь 28, 2011, 14:40
Множественное наследование от кьюобжектов не поддерживает мок


Название: Re: Виртуальное наследование от класса Qt
Отправлено: kambala от Сентябрь 28, 2011, 15:03
попробуй выделить какой-то общий интерфейс или класс (естественно не наследник QObject) и унаследовать оба своих класса от него


Название: Re: Виртуальное наследование от класса Qt
Отправлено: alex312 от Сентябрь 28, 2011, 18:28
Ну там не написано что нельзя  :) Можно, но просто это ничего хорошего не дает. т.к. QObject не есть виртуальный базовый класс для QWidget и др
эти две фразы:
Цитировать
только один из предков может быть наследником QObject
- отсюда (http://www.developer.nokia.com/Community/Wiki/%D0%91%D0%B0%D0%B7%D0%BE%D0%B2%D1%8B%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%81_QObject)
Цитировать
The QWidget class is the base class of all user interface objects. More...
 #include <QWidget>
Inherits: QObject and QPaintDevice.
- отсюда (http://doc.qt.nokia.com/4.8-snapshot/qwidget.html)

говорят мне что где то вы неправы.


Название: Re: Виртуальное наследование от класса Qt
Отправлено: Igors от Сентябрь 28, 2011, 18:56
эти две фразы:
...
говорят мне что где то вы неправы.
А может проверим? (а не только будем запоминать чужие фразы  :))

Код
C++ (Qt)
#include <QtGui>
 
struct Test1 : virtual public QObject {
int mData1;
};
 
struct Test2 : virtual public QObject {
int mData2;
};
 
struct Test3 : public Test1, public Test2 {
int mData3;
};
 
int main(int argc, char **argv)
{
QApplication app(argc, argv);
Test3 test3;
test3.mData1 = 1;
test3.mData2 = 2;
test3.mData3 = 3;
 
Test1 * test1 = (Test1 *) &test3;
Test2 * test2 = (Test2 *) &test3;
QObject * base1 = dynamic_cast<QObject *> (test1);
QObject * base2 = dynamic_cast<QObject *> (test2);
QObject * base3 = dynamic_cast<QObject *> (&test3);
printf("test1 = %p, base1 = %p\n"
  "test2 = %p, base2 = %p\n"
  "test3 = %p, base3 = %p\n",
test1, base1,
test2, base2,
&test3, base3);
 
return 0;
}
 


Название: Re: Виртуальное наследование от класса Qt
Отправлено: LisandreL от Сентябрь 28, 2011, 19:02
эти две фразы:
говорят мне что где то вы неправы.
Не вижу противоречия. QPaintDevice от QObject не наследуется.


Название: Re: Виртуальное наследование от класса Qt
Отправлено: alex312 от Сентябрь 29, 2011, 09:32
А может проверим? (а не только будем запоминать чужие фразы  :))
А может будем отвечать на посты в контексте ?
А может будем рассматривать код, приведенный топикстартером, а не выдумывать сферические тесты?


Название: Re: Виртуальное наследование от класса Qt
Отправлено: andrew.k от Сентябрь 29, 2011, 10:01
То что этот примитивный абстрактный пример компилится и работает. Это ничего еще не значит.
Синтаксически с ним все в порядке.

Проблемы могут возникнуть в более сложных классах с сигналами и слотами.
Это видимо ограничение метаобъектной системы qt. Иначе об этом не было бы написано.
Нельзя значит нельзя. Что тут обсуждать?


Название: Re: Виртуальное наследование от класса Qt
Отправлено: lit-uriy от Сентябрь 29, 2011, 17:08
"Виртуальное наследование с помощью QObject не поддерживается."
Тыц (http://doc.crossplatform.ru/qt/4.7.x/moc.html#multiple-inheritance-requires-qobject-to-be-first)


Название: Re: Виртуальное наследование от класса Qt
Отправлено: andrew.k от Сентябрь 29, 2011, 17:17
"Виртуальное наследование с помощью QObject не поддерживается."
Тыц (http://doc.crossplatform.ru/qt/4.7.x/moc.html#multiple-inheritance-requires-qobject-to-be-first)
Ты выдернул из контекста.
Прочитай целиком тему.


Название: Re: Виртуальное наследование от класса Qt
Отправлено: lit-uriy от Сентябрь 29, 2011, 17:53
>>Прочитай целиком тему.
За каким чёртом?

Код
C++ (Qt)
class A : public QObject {...};
class B : public A, public QWidget {...};
QWidget - наследник QObject, а виртуальное наследование QObject не поддерживается.


Название: Re: Виртуальное наследование от класса Qt
Отправлено: Igors от Сентябрь 29, 2011, 17:59
"Виртуальное наследование с помощью QObject не поддерживается."
Тыц (http://doc.crossplatform.ru/qt/4.7.x/moc.html#multiple-inheritance-requires-qobject-to-be-first)
Юра, то "тыц" пальцем в небо :) Не стоит повторять неграмотную фразу: не бывает "наследования с помощью", есть "наследование от". Поддерживать или нет решает С++, а не Qt, и поскольку QObject класс, то он может быть виртуально унаследован. А вот как он будет работать - то уже другой вопрос  :)

Представим себе что запрос Alf удовлетворен. Это капитальный геморрой для разработчика. Надо как-то "слить" слоты/сигналы из всех базовых классов, надо как-то решить конфликты: напр 2 базовых класса имеют слот с одним именем - какой активен? С др стороны множественное наследование - случай достаточно редкий, в большинстве случаев может быть без ущерба заменен членством. Поэтому гораздо проще и лучше сказать "нельзя!", это ясно и понятно для широкого круга пользователей  :)


Название: Re: Виртуальное наследование от класса Qt
Отправлено: lit-uriy от Сентябрь 30, 2011, 09:59
>>Поддерживать или нет решает С++, а не Qt
В контексте Qt - не верно. Это определяется мета-объектным компилятором - moc. И реализацией классов Qt (в Qt ни один класс-наследник QObject не имеет пометки "virtual" при наследовании, например, QWidget).

А так как наследование от QObject имеет смысл из-за метаобъектной системы (сигнал, слоты, свойства ...). То и получается, что С++ компилятор можно даже не рассматривать.

Наиболее распространённая хотелка (обоснованная) программистов - написать интерфейс с сигналами (или слотами), а затем наследоватся от QObject'ов и этого интерфейса, в Qt не возможна.



Название: Re: Виртуальное наследование от класса Qt
Отправлено: andrew.k от Сентябрь 30, 2011, 10:30
>>Поддерживать или нет решает С++, а не Qt
В контексте Qt - не верно. Это определяется мета-объектным компилятором - moc. И реализацией классов Qt (в Qt ни один класс-наследник QObject не имеет пометки "virtual" при наследовании, например, QWidget).

А так как наследование от QObject имеет смысл из-за метаобъектной системы (сигнал, слоты, свойства ...). То и получается, что С++ компилятор можно даже не рассматривать.

Наиболее распространённая хотелка (обоснованная) программистов - написать интерфейс с сигналами (или слотами), а затем наследоватся от QObject'ов и этого интерфейса, в Qt не возможна.


Невозможна или не разрешена?
А если сделать все внимательно, чтобы имена слотов и сигналов не пересекались. Будет ли работать?


Название: Re: Виртуальное наследование от класса Qt
Отправлено: shirushizo от Сентябрь 30, 2011, 10:41
Самое нормальное решение уже озвучили:
попробуй выделить какой-то общий интерфейс или класс (естественно не наследник QObject) и унаследовать оба своих класса от него
Выделяем класс C, в который уходит часть функционала, которую добавили в класс A
Код:
class C {...}; 
class D : public QObject, public C {...};
class B : public QWidget, public C {...};
Оба класс B и D получили необходимый функционал через класс C, и сигнал/слот и свойства от QObject. И вся проблема ;) Того гляди и moc выпендриваться не будет.


Название: Re: Виртуальное наследование от класса Qt
Отправлено: andrew.k от Сентябрь 30, 2011, 10:45
да это был теоретический вопрос, а не практический. так то все понятно.
просто чтобы лучше понимать устройство.


Название: Re: Виртуальное наследование от класса Qt
Отправлено: Igors от Сентябрь 30, 2011, 12:41
Выделяем класс C, в который уходит часть функционала, которую добавили в класс A
Код:
class C {...}; 
class D : public QObject, public C {...};
class B : public QWidget, public C {...};
Оба класс B и D получили необходимый функционал через класс C, и сигнал/слот и свойства от QObject. И вся проблема ;)
Так класс С не может быть потомком QObject, и это создает известные неудобства: приходится делать ему член-указатель и возиться с ним. Хотя ничего особо страшного/плохого нет.


Название: Re: Виртуальное наследование от класса Qt
Отправлено: shirushizo от Сентябрь 30, 2011, 13:45
да это был теоретический вопрос, а не практический. так то все понятно.
просто чтобы лучше понимать устройство.
В теории сам язык Си++ позволяет использовать в этом случае виртуальное наследование и любой компилятор с этим справится. Проблема в метаобъектной системе самой библиотеки Qt и в инструменте moc, который просто не поймет что вы от него хотите: какой из слотов/сигналов использовать, какой из Q_PROPERTY подразумевается - и никакой виртуальной таблицей здесь не обойдешься, просто не будет однозначности и даже, если всю эту б-гадельню получится запустить поведение будет непредсказуемо и неконтролируемо.


Название: Re: Виртуальное наследование от класса Qt
Отправлено: lit-uriy от Октябрь 01, 2011, 23:08
>>А если сделать все внимательно, чтобы имена слотов и сигналов не пересекались. Будет ли работать?
у меня не работало, точно не помню кто ругался, сам МОС или С++ на продукт МОСа
(П.С. В интерфейсе было объявлено несколько сигналов, в наследнике они посылались)