Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Приведение типов C++/QT
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Общие вопросы
fsMark
Писал недавно одному знакомому о приведении типов в QT, решил выложить на форум вдруг комунибудь будет полезно или ктонибудь дополнит(сам пишу на QT 4 месяца :))
На мой взгляд картина выглядить слкдующим образом:

стандартная конструкция:
classA* A = new classA;
classB* B = (classB*)A;
приведет указатель на classA к указателю на classB, это стандартный способ приведения указателей унаследованный от языка C, при таком приведении не производиться никаких проверок не на этапе компиляции не на этапе исполнения со всеми вытекающими последствиями.

В C++ введенны следующие более тонкие конструкции:

classA* A = new classA;
classB* B = static_cast<classB*>A;
Эта конструкция приведет указатель на classA к Указателю на classB при том условии что класс classB является наследдником класса classA

classA* A = new classA;
classB* B = dynamic_cast<classB*>A;
Эта конструкция действует аналогично static_cast, отличие заключается в том что производиться проверка на принадлежность обекта на который сыллается А класу В, для проверки использукется информатция о типах времени выполнения(RTTI) которая естественно должна быть включена на этапе компилятции(в болщенстве современных компиляторов включена по умолчанию).
Если проверка завершается неудачно то dynamic_cast вернет нулевой указатель.
В некоторых компиляторах dynamic_cast может не работать через границы разделяемых библиотек.

QT предоставляет свое средство для приведения указателей заместо dynamic_cast:
qobject_cast аналогичен dynamic_cast для подклассов QObject(для остальных классов результат не определен), но он не зависит от RTTI и может работать через границы разделяемых библиотек.

вот пример из ассистента:
QObject *obj = new QTimer; // QTimer inherits QObject
QTimer *timer = qobject_cast<QTimer *>(obj);
// timer == (QObject *)obj
QAbstractButton *button = qobject_cast<QAbstractButton *>(obj);
// button == 0

Кроме того для приведения указателей на классы унаследованные от QGraphicsItem(не наследник QObject) существует qgraphicsitem_cast.
ViGOur
Еще дополнить и можно будет оформить в статью. :)
void*
из Qt-шных, еще существуют такие касты:
qdbus_cast, qscriptvalue_cast, qstyleoption_cast и qvariant_cast.
Tonal
Для того, чтобы работал qobject_cast, нужно не только унаследоваться от QObject, но и добавить макрос Q_OBJECT в описание класса. Для остальных Qt-шных кастов тоже требуются некоторые телодвижения. В отличие от dynamic_cast для которого всё делается автоматом при наличии хотя бы одного виртуального метода. :)
fsMark
Если не добавлять макрос Q_OBJECT то особого смысла наследоваться от QObject нет, теряются все вкусности... типа сигналов и слотов.
Непонял какие телодвижения ты имеешь в виду, если можешь опиши подробней.
Tonal
Тем не менее, наследник QObject без Q_OBJECT вполне жизненная ситуация - например рабочий поток.

Про дополнительные телодвижения, нужно для каждого каста смотреть по месту. Например для qgraphicsitem_cast нужно переопределить virtual int QGraphicsItem::type () const так, чтобы он возвращал уникальное для всех использующихся в программе и плагинах наследников QGraphicsItem число.
Для остальных - копай ассистента.

Динамические касты для своей работы требуют дополнительную информацию связанную с экземпляром. В случае qobject_cast эту информацию добавляет moc, в случае qgraphicsitem_cast она достаётся из виртуальной функции, куда её явно положил разработчик. Для dynamic_cast компилятор автоматически связывает эту инфу с таблицей виртуальных методов.

Плюсы dynamic_cast в том, что он автоматом работает а любыми полиморфными объектами языка и в том, что компилятор может его заменить на static_cast в некоторых случаях (приведение наследника к базе).
Плюсы q*_cast в возможно меньшем объёме бинарика, и корректной работе на старых компиляторах.
kuler
про static_cast и dynamic_cast написано не шибко правильно
fsMark
Цитата(kuler @ 1.10.2008, 12:15) *
про static_cast и dynamic_cast написано не шибко правильно


Ждем спаведливой критики :)
kuler
Цитата(fsMark @ 1.10.2008, 12:27) *
Цитата(kuler @ 1.10.2008, 12:15) *
про static_cast и dynamic_cast написано не шибко правильно


Ждем спаведливой критики :)

вломы писать, там много, труп страуса почитайте
AD
Цитата(kuler @ 1.10.2008, 12:44) *
вломы писать, там много, труп страуса почитайте

Тогда нефиг хаять! Вообще, за такого рода посты я бы забанил. Что за ерунда? Вполне достоверная информация была приведена. Если она неполная, то можно дополнить, а не хаять!
ViGOur
Цитата(kuler @ 1.10.2008, 12:15) *
про static_cast и dynamic_cast написано не шибко правильно

Цитата(kuler @ 1.10.2008, 12:44) *
вломы писать, там много, труп страуса почитайте
дело в том, что если так говоришь, то нужно описать, что именно не так! Иначе лучше просто промолчать... ;)
kuler
static_cast срабатывает на этапе компиляции, проверяет типы на подобность, dynamic_cast срабатывает на этапе выполнения проверяя реально ли можно приравнять объекты, кроме того объекты должны быть полиморфны, нельзя приравнивать void*.
Исправляйте репутацию.
Litkevich Yuriy
Цитата(kuler @ 1.10.2008, 18:04) *
Исправляйте репутацию.
все в твоих руках.
Вот тема, в ней конкретные сообщения. Поправь их, добавь точности или укажи где ошибка и как должно быть, чтобы было без ошибки.

принесешь полезную информацию, репутация поднимится
Tonal
Цитата(kuler @ 1.10.2008, 18:04) *
static_cast срабатывает на этапе компиляции, проверяет типы на подобность, dynamic_cast срабатывает на этапе выполнения...

Я этому где-нибудь противоречил?
Перечитай внимательно что я написал. :)

Я не описывал поведение обоих приведений а всего лишь утверждал о их взаимозаменимости в частном случае.
Или ты можешь привести пункт стандарта, который запрещает то, о чём я написал?
kuler
Цитата(Tonal @ 2.10.2008, 14:15) *
Цитата(kuler @ 1.10.2008, 18:04) *
static_cast срабатывает на этапе компиляции, проверяет типы на подобность, dynamic_cast срабатывает на этапе выполнения...

Я этому где-нибудь противоречил?
Перечитай внимательно что я написал. :)

Я не описывал поведение обоих приведений а всего лишь утверждал о их взаимозаменимости в частном случае.
Или ты можешь привести пункт стандарта, который запрещает то, о чём я написал?

да я не тебе написал, а первому сообщению
Гость_Barabas_*
Благодарю за эту информацию! Искал именно это=)
Алексей1153
Цитата(kuler @ 1.10.2008, 17:04) *
Исправляйте репутацию.

готово!

==============================

моё ИМХО

1) использование static_cast иногда может быть вполне оправдано - для подстраховки на этапе компиляции.

2) Необходимость использования dynamic_cast:
a ) признак кривого проектирования. Равно как и явное приведение к void* и из него - тоже такой признак
b ) при поддержке чужого запутанного кода - это подстраховка в реалтайме (можно всегда результат каста проверить на ноль)
Поэтому лучше проектировать так, чтобы кастить через этот оператор не было необходимости.
Кроме того, для возможности применения dynamic_cast класс обязан иметь хотя бы одну виртуальную функцию, что не всегда приемлимо

3 ) Необходимость использования reinterpret_cast : см. п 2)a) . Но ещё иногда требуется, к примеру, при взамодействии с ранее написанным кодом на чистом си (пример - WinAPI , извещения WM_NOTIFY от стандартных контролов)

Критика принимается :)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2022 IPS, Inc.