Russian Qt Forum
Июнь 16, 2024, 00:35 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Приведение типов  (Прочитано 5358 раз)
Alp
Гость
« : Август 27, 2009, 11:17 »

Есть пара классов:
MyObject<-MyLabel<-MyExtLabel
         MySelectable<-'

MyObject<-MyAnotherUiObject
MySelectable<-'

У объектов MyObject есть метод parent() const, позволяющий получать предка вплоть до последнего уровня.
У объектов MySelectable есть метод SetState(int s), позволяющий менять статус "выбран/не выбран", в зависимости от которого меняется внешний вид.

При получении сообщения о нажатии/наведении указателя от контрола (MyExtLabel/MyAnotherUiObject/etc) классом приложения напрашивается следующий код для установления состояния для выбранного контрола и всех его предков:

Код
C++ (Qt)
void SetStateUpstair(const MyObject* start, const MyObject* end, int s)
{
MyObject* o = const_cast<MyObject*>(start); //FFFFFUUUUUUUUUUUUU!!!!!
 
   do
   {
    //Another FFFFFUUUUUUUUUUUUU!!!!
MySelectable* sel = dynamic_cast<MySelectable*>( o );
 
if( sel )
{
sel->SetState( s );
o = o->parent();
}
   } while( o != end );
}
 

dynamic_cast возвращает не 0, т.е. кастуется объект верно, для тех, кто наследует MySelectable, однако внутренние поля 'state' и 'prevState' содержат мусор (в конструкторе они инициализируются нулями), т.е. вроде как скастовалось-то неверно. И действительно, по завершении работы метода все статусы у всех контролов не изменяются.

Как бы это победить и какой раздел Страуструповской книжки мне надо перечитать ещё раз?
Записан
sergeyvl12
Гость
« Ответ #1 : Август 27, 2009, 11:57 »

На счет Страуструпа - не знаю, но по-моему тонкости dynamic_cast + множественное наследование хорошо описаны здесь:

http://msdn.microsoft.com/en-us/library/cby9kycs(VS.80).aspx

То что возвращается валидный указатель с мусором - ИМХО косяк компилятора.
Записан
Tonal
Гость
« Ответ #2 : Август 27, 2009, 12:09 »

У всех ли базовых классов есть виртуальные методы?
Каким компилятором какой версии компилишь?
Записан
Alp
Гость
« Ответ #3 : Август 27, 2009, 12:16 »

Я вот не помню, при иcпользовании dynamic_cast важно само наличие виртуальных функций или наличие перегруженных ВФ? Сами функции есть, перегрузки нет.

Платформа - win32, компилятор mingw-gcc3.4.5

C:\soft\Qt\2009.03\mingw\bin>.\gcc -v
Reading specs from ./../lib/gcc/mingw32/3.4.5/specs
Configured with: ../gcc-3.4.5-20060117-3/configure --with-gcc --with-gnu-ld --wi
th-gnu-as --host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --dis
able-nls --enable-languages=c,c++,f77,ada,objc,java --disable-win32-registry --d
isable-shared --enable-sjlj-exceptions --enable-libgcj --disable-java-awt --with
out-x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enabl
e-hash-synchronization --enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.5 (mingw-vista special r3)
Записан
sergeyvl12
Гость
« Ответ #4 : Август 28, 2009, 01:06 »

Налабал такой пример (см. ниже). Все работает как положено. Никаких сюрпризов. Компилятор абсолютно тот же... Можешь запустить этот примерчик у себя ?

Код:
#include <QtCore/QCoreApplication>

class MyObject
{
    int a;
public:
    MyObject()
        : a(0)
    {
    }
    virtual ~MyObject()
    {
    }
public:
    virtual bool isValid() const
    {
        return true;
    }
};

class MySelectable
{
    int state;
public:
    MySelectable()
        : state(0)
    {
    }
    virtual void setState( int s )
    {
        state = s;
    }
};

class MyLabel: public MyObject, public MySelectable
{
};

class MyExtLabel: public MyLabel
{
};

class MyAnotherUiObject: public MyObject, public MySelectable
{
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyObject* o1 = new MyAnotherUiObject();
    MySelectable* s1 = dynamic_cast<MySelectable*>(o1);
    s1->setState(1);
    MyObject* o2 = new MyExtLabel();
    MySelectable* s2 = dynamic_cast<MySelectable*>(o2);
    s2->setState(2);

    return a.exec();
}
Записан
Alp
Гость
« Ответ #5 : Август 28, 2009, 12:49 »

Всем спасибо, заработало магическим образом. =(
Записан
sergeyvl12
Гость
« Ответ #6 : Август 28, 2009, 13:59 »

Ну, так не бывает ...

Что изменил? Может проект пересобрал?
Записан
sergeyvl12
Гость
« Ответ #7 : Август 28, 2009, 14:01 »

У всех ли базовых классов есть виртуальные методы?
Каким компилятором какой версии компилишь?

Если нет, такой код даже не скомпилируется (ошибка на строчке с dynamic_cast<>(), проверял)
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.068 секунд. Запросов: 20.