LINUX.ORG.RU

[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)

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

★★★★★

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

yoghurt ★★★★★
()

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

MikeDM ★★★★★
()
Ответ на: комментарий от namezys

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

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

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

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

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

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

namezys ★★★★
()
Ответ на: комментарий от namezys

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

Везде стоит.

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

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

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

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

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

Gorthauer ★★★★★
() автор топика
Ответ на: комментарий от yoghurt

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

Gorthauer ★★★★★
() автор топика
Ответ на: комментарий от namezys

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

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

rival ★★
()
class Model : public AbstractContactModel, при этом 

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

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

Есть ли Q_OBJEСT?

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

alpha2
()
Ответ на: комментарий от TERRANZ

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

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


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

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

aho
()
Ответ на: комментарий от alpha2

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

Gorthauer ★★★★★
() автор топика

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

Gorthauer ★★★★★
() автор топика
Ответ на: комментарий от aho

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

aho
()
Ответ на: комментарий от Gorthauer

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

Везде стоит.

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

namezys ★★★★
()
Ответ на: комментарий от aho

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

Вроде можно:

class A {} class B {}

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

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

namezys ★★★★
()
Ответ на: комментарий от namezys

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

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

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

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

Gorthauer ★★★★★
() автор топика
Ответ на: комментарий от 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;
}
namezys ★★★★
()
Ответ на: комментарий от namezys

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

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

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


для «class A {} class B {}»?

aho
()
Ответ на: комментарий от aho

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

namezys ★★★★
()
Ответ на: комментарий от namezys

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

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

aho
()
Ответ на: комментарий от Gorthauer

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

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

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

aho
()
Ответ на: комментарий от namezys

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

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

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

aho
()
Ответ на: комментарий от Gorthauer

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

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

aho
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.