Russian Qt Forum

Программирование => С/C++ => Тема начата: Fregloin от Август 01, 2011, 14:31



Название: "Виртуальные" члены класса?
Отправлено: Fregloin от Август 01, 2011, 14:31
Есть базовый класс модуля устройства, к примеру CGenericModule.
Код:
#ifndef CGENERICMODULE_H
#define CGENERICMODULE_H

class   CEC;
class   QGenericModule;

class CGenericModule
{
protected:
    CEC             *   fparentEC;  //владелец
    QGenericModule  *   fmodule;    //связанный модуль на view
    virtual void        attachToGUIModule()=0;
    virtual void        detachFromGUIModule()=0;
public:
    CGenericModule(CEC * ParentEC);
    QGenericModule       *   module(){return fmodule;}
    void                setModule(QGenericModule * AModule);
    virtual void        update(){}
    virtual void        unlinkModule()=0;
};

#endif // CGENERICMODULE_H
От него наследуются несколько дочерних классов, как то - модуль базовый ввода/вывода (CIOModule), модуль питания (CPowerModule), модуль охлаждения (CCooler) и т.п.
В классе CGenericModule член
Код:
QGenericModule  *   fmodule;
хранит указатель на GUI объект, который отображается на сцене (иерархия GUI объектов похожа). Но в дочерних классах, мне нужно хранить fmodule уже типа GUI объекта (т.е. не QGenericModule, а QIOModule, QPowerModule, QCooler...).
Как можно добиться "виртуальности" члена fmodule, что бы в каждом классе он соотвествовал нужному типу (т.е. грубо перегрузить его тип). Раньше я делал так, в каждй дочерний класс добавлял новый приватный член уже нужного типа, а его значение приводил через dynamic_cast к нужному типу.
Является ли такой подход единственным? или задействовать шаблоны? хотя думаю могут возникнуть проблемы...


Название: Re: "Виртуальные" члены класса?
Отправлено: Fregloin от Август 01, 2011, 14:35
вот как делаю сейчас:
Код:
class CIOModule : public CGenericModule
{
protected:
    bool        speedChanged;
    bool        stateChanged;
    bool        countChanged;
    void        attachToGUIModule();
    void        detachFromGUIModule();
    QIOModule   *  fioModule;
public:
    CIOModule(CEC * ParentEC);
    uint8_t OldState;
    uint16_t OldSpeed;
    uint16_t    OldCount;
    uint8_t* StatePtr;
    uint16_t* SpeedPtr;
    uint16_t* CountPtr;
    void        update();
    void        unlinkModule();
};

Код:
void        CIOModule::attachToGUIModule()
{
    fioModule = dynamic_cast<QIOModule*>(fmodule);
    if(fioModule)
    {
        fioModule->beginUpdate();
        fioModule->setCurrentStateColor(Qt::white);
        fioModule->setSpeedText(linked);
        fioModule->setCountText(linked);
        fioModule->endUpdate();
    }
}

void    CIOModule::update()
{
    if(!fioModule) return;

    speedChanged = countChanged = stateChanged = false;

    if(StatePtr && OldState!=*StatePtr)
    {
        OldState = *StatePtr;
        stateChanged = true;
    }

    if(SpeedPtr && OldSpeed!=*SpeedPtr)
    {
        OldSpeed = *SpeedPtr;
        speedChanged = true;
    }

    if(CountPtr && OldCount!=*CountPtr)
    {
        OldCount = *CountPtr;
        countChanged = true;
    }

    if(stateChanged || countChanged || speedChanged)
    {
        fioModule->beginUpdate();

        if(stateChanged)
        {
            if(OldState==0)
            fioModule->setCurrentStateColor(lightRed);
            else
            fioModule->setCurrentStateColor(lightGreen);
        }

        if(speedChanged) fioModule->setSpeedText(QString::number(OldSpeed));
        if(countChanged) fioModule->setCountText(QString::number(OldCount));

        fioModule->endUpdate();
    }
}


Название: Re: "Виртуальные" члены класса?
Отправлено: Fregloin от Август 01, 2011, 14:37
т.е. не хочется использовать часто dynamic_cast во всех методах класса CIODevice, или другого не дано?


Название: Re: "Виртуальные" члены класса?
Отправлено: SASA от Август 01, 2011, 14:42
А зачем базовый класс содержит QGenericModule  *   fmodule?


Название: Re: "Виртуальные" члены класса?
Отправлено: Fregloin от Август 01, 2011, 14:54
Код:
#include <stddef.h>
#include "cgenericmodule.h"
#include "qgenericmodule.h"
#include "qiomodule.h"

CGenericModule::CGenericModule(CEC * ParentEC)
{
    fparentEC = ParentEC;
    fmodule = NULL;
}

void    CGenericModule::setModule(QGenericModule * AModule)
{
    if(fmodule!=AModule)
    {
        if(!AModule)
        {
            detachFromGUIModule();
        }
        fmodule = AModule;
        if(fmodule)
        {
            attachToGUIModule();
        }
    }
}
изза функции setModule(), в которой я устанавливаю указатель на новый GUI объект, вызывая при этом виртуальные функции привязок для каждого отдельного класса, а fmodule содержит указатель на текущий GUI объект.


Название: Re: "Виртуальные" члены класса?
Отправлено: m_ax от Август 01, 2011, 15:21
Чем не устраивает вариант оформить CGenericModule в виде шаблона?
Код
C++ (Qt)
template <class TModule>
class CGenericModule
{
protected:
   CEC             *   fparentEC;  //владелец
   TModule  *   fmodule;    //связанный модуль на view
   virtual void        attachToGUIModule()=0;
   virtual void        detachFromGUIModule()=0;
public:
   CGenericModule(CEC * ParentEC);
   TModule       *   module(){return fmodule;}
   void                setModule(TModule * AModule);
   virtual void        update(){}
   virtual void        unlinkModule()=0;
};
 
class CIOModule : public CGenericModule<QIOModule>
{
...
};
 


Название: Re: "Виртуальные" члены класса?
Отправлено: Igors от Август 01, 2011, 16:31
Код:
void        CIOModule::attachToGUIModule()
{
    fioModule = dynamic_cast<QIOModule*>(fmodule);
    if(fioModule)
    {
        fioModule->beginUpdate();
        fioModule->setCurrentStateColor(Qt::white);
        fioModule->setSpeedText(linked);
        fioModule->setCountText(linked);
        fioModule->endUpdate();
    }
}
Явно нехорошо, т.к. CIOModule знает все-все о QIOModule (хотя не порожден от него). Также то что в скобках смотрится как метод. Почему бы для начала не пойти по простейшему пути: добавить все возможные вызовы в виртуалы базового класса. Тогда бы выглядело так
Код
C++ (Qt)
void CIOModule::attachToGUIModule()
{
   if (fioModule))
    fioModule->attachAction();  // возможно с параметрами
}
 


Название: Re: "Виртуальные" члены класса?
Отправлено: SASA от Август 02, 2011, 12:23
Я бы делал в дочерних классах сделал функции типа QIOModule * getIOModule();
а в ней динамик каст или qobject_cast.