Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Ошибка invalid conversion from `QWidget*' to `QComboBox*'
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Общие вопросы
kvak
Имеется:
QComboBox *oe_units;
*PM - объекта собственного класса
*TABLE_ELITE - таблица QTableWidget, которая является данным класса, который представляет объект PM

Не рабоатает вот такая нструкция:
oe_units = PM->TABLE_ELITE->cellWidget(e, f);

Код ошибки:
code\order.cpp:104: error: invalid conversion from `QWidget*' to `QComboBox*'

Задача получить через функцию cellWidget, выполненную для таблицы, которая принадлежит классу,
представленному объектом PM, указатель на тот самый виджет. К этому времени в этой ячейке с адресом
(e, f) находится виджет QComboBox.
Так как функция cellWidget возвращает указатель полученного виджета, то по идее мой указатель oe_units
должен после выполнения инструкции указывать на тот самый виджет. Сам виджет QComboBox не приватный.

В чем тут может быть ошибка ? Правильная ли сама инструкция ?
Алексей1153
приведи тип указателя (на свой страх и риск - следи, чтобы там был указатель именно на комбу)
oe_units = (QComboBox*)PM->TABLE_ELITE->cellWidget(e, f);


molchanoviv
проверь не стоит ли у тебя в oe_units = new QComboBox вместо QComboBox QWidget?
igor_bogomolov
oe_units = qobject_cast<QComboBox*>(PM->TABLE_ELITE->cellWidget(e, f));
kwisp
Цитата(Алексей1153 @ 16.9.2010, 12:50) *
oe_units = (QComboBox*)PM->TABLE_ELITE->cellWidget(e, f);

извини, позанудствую. )
такое приведение типов не только в Qt не рекомендовано - даже в С++ не рекомендуют.
*. не наглядно и трудночитаемое приведение
*. ты не знаешь какой _cast за ни прячется.
*. что будет в случае неудачного приведения? - страх и риск?
*. ...
Алексей1153
Цитата(kwisp @ 16.9.2010, 15:24) *
*. не наглядно и трудночитаемое приведение
*. ты не знаешь какой _cast за ни прячется.
*. что будет в случае неудачного приведения? - страх и риск?
*. ...

всё - чушь (ИМХО). Во-первых, гораздо нагляднее, чем синтаксис каста. А потом, я всегда знаю, что у меня в МОЕЙ программе где делается :) Вот с чужими модулями, тут я согласен, неплохо прокастовать и проверить на ноль. Но это тоже когда-нибудь не спасёт :D
kwisp
Цитата(Алексей1153 @ 16.9.2010, 13:49) *
всё - чушь (ИМХО).

тогда молчу.
Алексей1153
Цитата(kwisp @ 16.9.2010, 16:43) *
тогда молчу.

дык, зачем молчать, я могу быть и не прав :) Доводы я бы послушал
kwisp
Цитата(Алексей1153 @ 16.9.2010, 15:09) *
я могу быть и не прав

доказать тебе это, все равно что заставить меня сейчас приводить доводы ;)
так что проехали ...
Litkevich Yuriy
Цитата(kwisp @ 16.9.2010, 16:24) *
даже в С++ не рекомендуют
kwisp прав, вот стиль описанный в Си++:
char ch = 0x01;
int = int(ch);
т.е. приведение типа через конструктор типа, вместо Сишного:
char ch = 0x01;
int = (int)ch;


Ну и cast_* само собой
kwisp
Цитата(Litkevich Yuriy @ 16.9.2010, 15:48) *
Ну и cast_* само собой

ну и конечно же различные
operator Type()

kvak
А если в этом случае
oe_units = qobject_cast<QComboBox*>(PM->TABLE_ELITE->cellWidget(e, f));
допустим, в ячейке (e, f) нет виджета QComboBox, то как себя программа поведет ?
igor_bogomolov
oe_units будет равна нулю. Не забывай делать проверку и проблем не будет
Алексей1153
Цитата(Litkevich Yuriy @ 16.9.2010, 17:48) *
kwisp прав, вот стиль описанный в Си++:
char ch = 0x01;
int = int(ch);

вообще-то речь про приведение указателей была :) А там, как ни крути, это адрес и всё тут. Какие нафиг конструкторы ? :)
DEADHUNT
Цитата(Алексей1153 @ 16.9.2010, 22:10) *
вообще-то речь про приведение указателей была :) А там, как ни крути, это адрес и всё тут. Какие нафиг конструкторы ? :)

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

не хочешь не используй ни касты ни приводящие конструтокры ни операторы Type(). и приводи указатели старым способом. хозяин барин.
Алексей1153
Цитата(DEADHUNT @ 17.9.2010, 0:16) *
адреса вообще-то тоже требуется корректировать(при необходимости).

хоть один пример в студию. Пока что я не могу придумать такой случай

kwisp, да нет, у меня нет привычек от СИ , я сразу с C++ начал. Каст использовать или нет - не вижу необходимости в нём, а выглядит неэстетично :) Вообще, я к метаданным о типе отрицательно отношусь (это мой личный баг :D )
kwisp
Цитата(Алексей1153 @ 16.9.2010, 22:28) *
не вижу необходимости в нём

ладно раз уж начал песню допою до конца. тему потом разделим.
Цитата(Алексей1153 @ 16.9.2010, 22:28) *
Каст использовать или нет - не вижу необходимости в нём, а выглядит неэстетично

т.е. ты всегда уверен что приведение закончится успешно?


Цитата(Алексей1153 @ 16.9.2010, 22:28) *
хоть один пример в студию. Пока что я не могу придумать такой случай

та легко.
при освобождении памяти ты даешь delete указатель - как по адресу delete определяет сколько памяти освободить? каков размер обЪекта?
DEADHUNT
Цитата(Алексей1153 @ 16.9.2010, 22:28) *
хоть один пример в студию. Пока что я не могу придумать такой случай

class A {
};

class B : public virtual A {
};

class C: public B, public virtual A {
};

C *c = new C;
A *a = (A *) c;

ну и ещё что-то там наворотить когда статически нельзя определить смещение базового класса(надо использовать dynamic_cast).
Алексей1153
Цитата(kwisp @ 17.9.2010, 0:42) *
т.е. ты всегда уверен что приведение закончится успешно?

конечно :) Это лишь снятие ответственности с компилятора, который паникует при попытке присвоить адрес объекта типа родителя указателю на объекта типа дитёнка (наоборот можно, он даже не пикнет). Более ничего при этом не происходит


Цитата(kwisp @ 17.9.2010, 0:42) *
та легко.
при освобождении памяти ты даешь delete указатель - как по адресу delete определяет сколько памяти освободить? каков размер обЪекта?

это не пример. Во первых, АДРЕС не поменяется от этого. Во вторых, для таких случаев должен быть виртуальный деструктор, либо ты уж учитывай, какой тип удаляется и приведи его перед удалением

А DEADHUNT говорил
Цитата(DEADHUNT @ 17.9.2010, 0:16) *
адреса вообще-то тоже требуется корректировать


DEADHUNT, в твоём примере адрес не меняется и не корректируется тоже )

я вредное, я знаю... Но пока не увидел убедительных объяснений обязаловки применения каста :)
kwisp
Цитата(Алексей1153 @ 16.9.2010, 22:49) *
это не пример. Во первых, АДРЕС не поменяется от этого. Во вторых, для таких случаев должен быть виртуальный деструктор, либо ты уж учитывай, какой тип удаляется и приведи его перед удалением

адресс не поменяется, поменяется "значение указателя" ведь он тем или иным способом хранит информацию о ТИПЕ!
при приведении типов старым способом компилер должен переберать сначала static_cast если не уместно то reinterpret_cast потом может взять dynamic_cast.
чаще всего берется reinterpret_cast не проверяются типы и т.д. т т.п.
BRE
Цитата(Алексей1153 @ 16.9.2010, 22:50) *
я вредное, я знаю... Но пока не увидел убедительных объяснений обязаловки применения каста :)

Давай смотреть. :)
#include <iostream>

class A
{
    int val1;
};

class B
{
    int val2;
};

class C : public A, public B
{
    int val3;
};

int main()
{
    // Создали объект класса B (он содержит одну(!) переменную типа int)
    B bObj;

    // Спокойно преобразовали ее к типу C, который должен содержать три(!) переменных типа int.
    // Давай попробуем записать и переменные var2 и var3, для которых память не выделялась.
    C *c1 = (C*)&bObj;
    std::cout << (void *)c1 << std::endl;

    // Попробуем тоже с кастом. На этапе компиляции нам скажут, что мы не правы.
    C *c2 = dynamic_cast<C*>( &bObj );
    std::cout << (void *)c2 << std::endl;

    return 0;
}

Сишное преобразование ничего не контролирует, с его помошью я могу преобразовать QString к QWidget, последствия правда будут не хорошие.

Насчет корректировки адреса указателя.
Попробуй с теми же классами выполнить следующие преобразования:
    C c;
    std::cout << (void *)&c << std::endl;
    
    A *a = dynamic_cast<A*>( &c );
    std::cout << (void *)a << std::endl;

    B *b = dynamic_cast<B*>( &c );
    std::cout << (void *)b << std::endl;

И посмотри как будет меняться указатель.
Кстати сишные преобразования тоже так умеют. :)
DEADHUNT
Цитата(BRE @ 16.9.2010, 23:06) *
Сишное преобразование ничего не контролирует, с его помошью я могу преобразовать QString к QWidget, последствия правда будут не хорошие.

в принципе всё контролирует кроме dynamic_cast
Цитата
5.4
Explicit type conversion (cast notation)
[expr.cast]
1 The result of the expression (T) cast-expression is of type T. The result is an lvalue if T is an lvalue reference
type or an rvalue reference to function type and an xvalue if T is an rvalue reference to object type; otherwise
the result is a prvalue. [ Note: if T is a non-class type that is cv-qualified, the cv-qualifiers are ignored when
determining the type of the resulting prvalue; see 3.10. — end note ]
2 An explicit type conversion can be expressed using functional notation (5.2.3), a type conversion operator
(dynamic_cast, static_cast, reinterpret_cast, const_cast), or the cast notation.
cast-expression:
unary-expression
( type-id ) cast-expression
3 Any type conversion not mentioned below and not explicitly defined by the user (12.3) is ill-formed.
4 The conversions performed by
— a const_cast (5.2.11),
— a static_cast (5.2.9),
— a static_cast followed by a const_cast,
— a reinterpret_cast (5.2.10), or
— a reinterpret_cast followed by a const_cast,

поэтому возможно придумать некоторый пример с полиморфными классами где будет применён reinterpret_cast.
kwisp
Цитата(Алексей1153 @ 16.9.2010, 22:50) *
Но пока не увидел убедительных объяснений обязаловки применения каста

тфу.
ты наверное прикалываешься - открой страуструпа (или любой другой весомый материал) стандарт в конце концов и почитай!
BRE
Цитата(DEADHUNT @ 16.9.2010, 23:10) *
в принципе всё контролирует кроме dynamic_cast

Мы говорим про указатели, ты хочешь сказать, что мне компилятор не даст так сделать?
    QString str;
    QWidget *w = (QWidget*)&str;

Проверь сам.
DEADHUNT
Цитата(BRE @ 16.9.2010, 23:17) *
Мы говорим про указатели, ты хочешь сказать, что мне компилятор не даст так сделать?

я такого не говорил, в данном случае компилятор применит reinterpret_cast(как описано выше), имелось ввиду что когда будет возможно применить безопасное преобразование, компилятор его применит(только в тех случаях которые описаны в стандарте)
Алексей1153
BRE, ну ты каких-то далёких от реальной жизни извращений набацал )) В которых принято специальные методы в классах делать, в коих вся темнота должна вручную разбираться, без всяких кастов. Я про это и говорю как раз

Цитата
Спокойно преобразовали ее к типу C,

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

Цитата(kwisp @ 17.9.2010, 1:11) *
открой страуструпа (или любой другой весомый материал) стандарт в конце концов и почитай!

не, не аргумент. Мясо давай, мясо ))
kwisp
Цитата(Алексей1153 @ 16.9.2010, 23:28) *
не, не аргумент. Мясо давай, мясо ))

колиника доктора Верховцева по тебе плачет. )
убеждать людей в очевидных вещах - глупая затея. потому что убеждать не надо они ОЧЕВИДНЫЕ.
BRE
Цитата(Алексей1153 @ 16.9.2010, 23:28) *
указатель от родителя к дитю нельзя спокойно приводить, надо при этом сильно волноваться и думать :)

Вот-вот, поэтому лучше сразу подружиться с кастами и пользоваться ими. Тогда компилятор будет сильно помогать не допустить ошибку при преобразовании.

Алексей1153
BRE, я такие ошибки не допускаю )

Цитата(kwisp @ 17.9.2010, 1:31) *
убеждать людей в очевидных вещах - глупая затея. потому что убеждать не надо они ОЧЕВИДНЫЕ.

это ты точно заметил )) Поэтому я тебя и не убеждаю.

Вообще, сильно отклонились от причины моего возмущения - а причина была такова, что, раз уж известно, что там у него должен лежать QComboBox* , то приводить (QComboBox*)(QWidget*) можно без всяких кастов.

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