LINUX.ORG.RU
 
Gorthauer

[C++/Qt] Чудеса с приведением типов


0

1

Имеется некий объект типа

class Model : public AbstractContactModel, при этом 

AbstractContactModel наследуется от QAbstractItemModel

потом этот указатель приводится к QObject'у и отдается дальше. И где-то позже делается вот так:

	object = ServiceManager::getByName("ContactModel");
	p->model = qobject_cast<AbstractContactModel*>(object);
	qDebug() << object << p->model << qobject_cast<QAbstractItemModel*>(object);

и получаем в результате

Core::SimpleContactList::Model(0x8dafa0) QObject(0x0)  Core::SimpleContactList::Model(0x8dafa0)

Что это за магия такая? Вроде все объекты на момент вызова полностью сконструированные. Но других идей у меня нету.

ПОСАДИ КОМПЬЮТЕР НА ЦЕПЬ И ЗАСТАВЬ ЛАЯТЬ!

домашняя автоматизация: сделай сам; лучший подарок для техногика

http://www.unicontrollers.com/products/unc01x

[#]  
namezys

Q_OBJEcT макрос стоит?

Зачем вам этот qobject_cast вообще? есть же более быстрый dynamic_cast

*** ()
[#]  
yoghurt

Клево. А p->model какого типа? В дебаггере проходить не пробовал?

***** ()
[#]  
MikeDM

Это древняя С магия. указатели и адреса.

*** ()
[#] Ответ на: комментарий от namezys 24.03.2011 19:38:26  
yoghurt

>Зачем вам этот qobject_cast вообще? есть же более быстрый dynamic_cast

>более быстрый dynamic_cast

ГГг, учитывая, что dynamic_cast емнип самый тормозной из всех стандартных _cast-ов, я даже боюсь представить, что там творится с qobject_cast.

***** ()
[#] Ответ на: комментарий от yoghurt 24.03.2011 19:40:22  
namezys

ой. я могу рассказать. в общем то у объектов есть статический куски, которые работают с qt meta type, из них выдирается id объекта и его текстовое имя, а потом идет поиск по лийненому массиву строк.

Как-то так коротко. Магия со сравнением строк, в отличает от dynamic_cast, где проход по дереву, построенному компилятором и сравнение id типов (которые правда загружаются через динамическую таблицу)

*** ()
[#] Ответ на: комментарий от zombiegrinder_6000 24.03.2011 19:41:02  
namezys

> Здесь бы и статик_каста хватило

Убить на фиг. Где какие гарантии?

*** ()
[#] Ответ на: комментарий от namezys 24.03.2011 19:42:38  

>Где какие гарантии?

Может и есть гарантии, из контекста непонятно.

()
[#] Ответ на: комментарий от namezys 24.03.2011 19:42:38  
aho

> Убить на фиг. Где какие гарантии?

компилятор ошибку выдаст, если что

()
[#] Ответ на: комментарий от aho 24.03.2011 19:45:17  
TERRANZ

неа, компилятор схавает
ошибка вылетит в рантайме

** ()
[#] Ответ на: комментарий от namezys 24.03.2011 19:38:26  
Gorthauer

>Q_OBJEcT макрос стоит?

Везде стоит.

>есть же более быстрый dynamic_cast

Мы уже решили везде юзать этот тип кастов. Да и dynamic_cast более компиляторозависимый. Со всяким бредом типа Symbian C++ может ботва начаться.

>Клево. А p->model какого типа? В дебаггере проходить не пробовал?

struct ModulePrivate
{
	~ModulePrivate() {}
	QWidget *widget;
	AbstractContactModel *model;
	AbstractContactListWidget *contactListWidget;
	QScopedPointer<ActionGenerator> tagsGenerator;
};

Пробовал, все указатели хорошие, при замене на static_cast работает. Но блин это не вариант. Мне интересно понять, что это вообще за бага? И как такое может быть?

*** ()
[#] Ответ на: комментарий от yoghurt 24.03.2011 19:40:22  
Gorthauer

Логично, остальные касты в compile time происходят. Кстати на clang'е падает в любом случае. а на gcc только при соблюдении определенных условий. Это точно не может быть порчей памяти?

*** ()
[#] Ответ на: комментарий от namezys 24.03.2011 19:38:26  

> Зачем вам этот qobject_cast вообще? есть же более быстрый dynamic_cast

Когда я последний раз проверял, qobject_cast был быстрее. Допускаю, что мой тест был неадекватен.
Можешь предоставить свой?

** ()
[#]  
class Model : public AbstractContactModel, при этом 

А при наследовании в AbstractContactModel, QAbstractItemModel на первом месте стоит?

Есть ли множественное наследование наследников QObject?

Есть ли Q_OBJEСT?

Я вообще удивляюсь, в Qt столько граблей разложено, неужели нельзя было нормально написать.

* ()
[#] Ответ на: комментарий от TERRANZ 24.03.2011 19:48:15  
aho

> неа, компилятор схавает
> ошибка вылетит в рантайме


можно пример? я по-быстрому накидал несколько наследованных классов, gcc честно наругалось:

invalid static_cast from type ‘A*’ to type ‘D*’

()
[#] Ответ на: комментарий от alpha2 24.03.2011 19:55:29  
Gorthauer

Нет там множественного наследования, Q_OBJECT есть, иначе бы оно в qdebug() выдавало другую хрень

*** ()
[#] Ответ на: комментарий от aho 24.03.2011 19:56:23  
Gorthauer

А теперь тоже самое, но для указателей

*** ()
[#] Ответ на: комментарий от Gorthauer 24.03.2011 20:05:19  
aho

> А теперь тоже самое, но для указателей

"‘A*’ to type ‘D*’"

()
[#] Ответ на: комментарий от aho 24.03.2011 20:07:30  
Gorthauer

Ога и смотри, выдаст ли он ошибку

*** ()
[#]  
Gorthauer

dynamic_cast прокатил... Я решительно не понимаю от чего qobject_cast ломается

*** ()
[#] Ответ на: комментарий от namezys 24.03.2011 19:38:26  

>есть же более быстрый dynamic_cast

пруфлинк?

* ()
[#] Ответ на: комментарий от Gorthauer 24.03.2011 20:12:06  
aho

> Ога и смотри, выдаст ли он ошибку

бл% :) что "ога" - я сразу на указателях проверял:

D* d = static_cast<D*>( a );
()
[#] Ответ на: комментарий от aho 24.03.2011 20:13:46  
aho

и да - рабочий вариант и нерабочий варианты я и сам могу получить, мне интересно увидеть "компилятор схавает, ошибка вылетит в рантайме"

()
[#] Ответ на: комментарий от TERRANZ 24.03.2011 19:48:15  
namezys

> неа, компилятор схавает

>ошибка вылетит в рантайме

Причем скорей всего трудноразрешимая

*** ()
[#] Ответ на: комментарий от Gorthauer 24.03.2011 19:50:31  
namezys

>> Q_OBJEcT макрос стоит?

> Везде стоит.

И в вашей асбтарктной модели тоже? Он должен быть в объекте, к которому вы кастите

*** ()
[#] Ответ на: комментарий от namezys 24.03.2011 20:17:51  
aho

> Причем скорей всего трудноразрешимая

тогда реквест насчет примера и к вам

()
[#] Ответ на: комментарий от reader 24.03.2011 20:13:04  
namezys

>> есть же более быстрый dynamic_cast

> пруфлинк?

Мозги. И почитать, как работает qt meta type и gcc

*** ()
[#] Ответ на: комментарий от aho 24.03.2011 20:18:48  
namezys

блин. пример, пример

Вроде можно:

class A {} class B {}

A *a = new A; B *b = sttaic_cast<B*>(a);

намешайте туда что нить в классы и упадет

*** ()
[#] Ответ на: комментарий от namezys 24.03.2011 20:21:26  
aho

> B *b = sttaic_cast<B*>(a);

"Вроде можно" - нельзя

()
[#] Ответ на: комментарий от namezys 24.03.2011 20:18:47  
Gorthauer

И в абстрактной и в реализации, везде макрос есть.

>тогда реквест насчет примера и к вам

	object = new QObject();
	p->model = static_cast<AbstractContactModel*>(object);

Вопросы есть?

*** ()
[#] Ответ на: комментарий от aho 24.03.2011 20:22:21  
namezys

код пожалусто. я один раз такое проделал - сработало

*** ()
[#] Ответ на: комментарий от Gorthauer 24.03.2011 20:22:50  
aho

> Вопросы есть?

да - я просил пример, который:

а) скомпилируется
б) упадет

()
[#] Ответ на: комментарий от namezys 24.03.2011 20:24:55  
namezys
class A { int a; };
class B : public A { public: int b; };

int main()
{
        A* a = new A;
        B* b = static_cast<B*>(a);
        return b->b;
}
*** ()
[#] Ответ на: комментарий от aho 24.03.2011 20:25:48  
namezys
typedef void(*ff)();

class A { int a; };
class B : public A { public: int b; ff f; };

int main()
{
        A* a = new A;
        B* b = static_cast<B*>(a);
        b->f();
        return b->b;
}
*** ()
[#] Ответ на: комментарий от namezys 24.03.2011 20:24:55  
aho

> код пожалусто.

если нет явного преобразования из T1 в T2 static_cast не сработает, хоть снизу-вверх, хоть для вообще не связанных классов, можете сами быстро накидать

> я один раз такое проделал - сработало


для "class A {} class B {}"?

()
[#] Ответ на: комментарий от namezys 24.03.2011 20:28:39  
aho
b->f();

юмор оценил

()
[#] Ответ на: комментарий от aho 24.03.2011 20:29:40  
namezys

Не. Ну не для связанных конечно не сработает. В этом случае вообще ничего вычислить нельзя

*** ()
[#] Ответ на: комментарий от aho 24.03.2011 20:31:12  
namezys

Аналогично будет при работе с виртуальными функциями

*** ()
[#] Ответ на: комментарий от aho 24.03.2011 20:25:48  
Gorthauer

Ты не поверишь, но этот пример скомпилится и гарантированно упадет

*** ()
[#] Ответ на: комментарий от namezys 24.03.2011 20:31:25  
aho

> Ну не для связанных конечно не сработает. В этом случае вообще ничего вычислить нельзя

поэтому я тут и выпрашиваю уже который раз пример, где static_cast даст неверный результат :)

()
[#] Ответ на: комментарий от aho 24.03.2011 20:32:49  
namezys

Ну вот выше я написал. Неверный результат. Вот руки и отрывать надо.

*** ()
[#] Ответ на: комментарий от Gorthauer 24.03.2011 20:32:46  
aho

> Ты не поверишь, но этот пример скомпилится и гарантированно упадет

./1.cpp:1: error: expected constructor, destructor, or type conversion before ‘=’ token
./1.cpp:2: error: expected constructor, destructor, or type conversion before ‘->’ token

не компилируется :( а если серьезно - минимальный рабочий пример можно?

()
[#] Ответ на: комментарий от namezys 24.03.2011 20:33:34  
aho

> Ну вот выше я написал. Неверный результат. Вот руки и отрывать надо.

то, что ты написал - даже не отработает, я написал почему, а "b->b" вернет правильное значение

П.С. ну неужели так трудно проверить свой же пример, и оформить его нормально с выводом результата :)

()
[#] Ответ на: комментарий от namezys 24.03.2011 20:34:51  
aho

> Мой чем плох?

см. мой предыдущий пост

()
[#] Ответ на: комментарий от aho 24.03.2011 20:34:04  
Gorthauer

Логично, он из контекста вырван, в контексте он компилится и падает

*** ()
[#] Ответ на: комментарий от Gorthauer 24.03.2011 20:37:14  
aho

> Логично, он из контекста вырван, в контексте он компилится и падает

возможно, но где он падает и почему - к сожалению проверить не представляется возможным

()
[#] Ответ на: комментарий от aho 24.03.2011 20:36:07  
namezys

я написал 2 примера

В первом случае везет и ты получаешь 0 - все отработает. Во втором - падение

*** ()
[#] Ответ на: комментарий от namezys 24.03.2011 20:21:26  

Ты вообще компилировать-то пробовал? Или так, на бумажке программируешь?

()