Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Создание класса-обертки


Автор: REZiaMIX 27.10.2008, 22:55
Есть класс TAnimation , с функцией Render... Функция использует глобальные переменные(от которых в посл. надо избавиться) .
+ класс TAnimations (метод Render тоже присутствует), представляющий собой массив анимаций , и функции для массовой их обработки - в чистом виде не используется , только наследуется.
Итого , имеем множество классов например:
TBullets,THumans - все наследуют TAnimations.
Надо сделать класс-обертку для всей анимации, но проблема в том , что классов может быть неизвестное кол-во , и каждый раз дописывать код в обертку не красиво и не гибко.
Каким образом реализовать такой класс(в полиморфизме и тд не очень разбираюсь) , с учетом того , что у всех исходных есть функция Render?

Пояснение:
Код

class TAnimation
{
    void Render(...){...};
};

class TAnimations
{
    vector <TAnimation> AllAnims; 
    
    void RenderAll(...)
    {
        // Рендрим все объекты из списка
    }
};


class THumans : public TAnimations
{
....
};

class TBullets : public TAnimations
{
....
};

class All {
 // сюда переписываем глобальные переменные
 ???? THumans ????
 ???? TBullets ????
    void RenderAll
    {
        /// ... рендрим все
    }
};



Есть вариант , хранить в векторе указатель на функции рендера , и вызывать их в цикле,
но все исходные классы должны получать те глобальные переменные(можно передать как аргумент).
Но что то мне подсказывает , что есть более правильный выход!

В идеале бы хотелось так(понятно что не будет работать , но для примера):
Код

TBullets bullets1;
THumans humans1;

TAll AllObjects;
AllObjects.push_back(bullets1);        //error   
AllObjects.push_back(humans1);     //error
AllObjects.RenderAll(...);


Заранее сенкс за ответы!


Автор: mes 27.10.2008, 23:11
Код

class IAnimation
{
   public:
         virtual void Render (..) = 0;
};

class Animations
{
    public:
       void Clear() {..};
       void AddAnimation    ( IAnimation * p) { ... }
       void RemoveAnimation ( IAnimation * p) { ... }
       void Render (.. ) {  for  (std::vector<IAnimation* >::iterator it = m_vAnim.begin(); it!=m_vAnim.end(); ++it)  if (*it) *it->Render(...);  }

    private:
       std::vector<IAnimation* > m_vAnim;
};

class Human : public IAnimation
{
   public:
         virtual void Render (..) { ... }
};

class Bullet : public IAnimation
{
   public:
         virtual void Render (..) { ... }
};
... 
Animations anims; 
anims.AddAnimation (new Human);
anims.AddAnimation (new Human);
anims.AddAnimation (new Bullet);
anims.Render (..);

Автор: REZiaMIX 27.10.2008, 23:19
Этот кусок кода уже реализован , вопрос стоит в другом;
Код

class TAllAnimation
{
       TBullets AllBullets;
       THumans AllHumans;
       //Каждый раз добавлять
      
        void RenderAll(...)
        {
                  AllBullets->Render(...);
                  AllHumans->Render(...);
                  //Каждый раз добавлять
        }
};


Соответственно если я напишу класс TFlowers, то в класс TAllAnimation надо будет дописать TFlowers в двух местах , 
нужно сделать обобщенный рендер , не в зависимости от класса(при условии наличия у них фции render)

Цитата

std::vector<IAnimation* > m_vAnim;

Не будет ли ошибкой добавление в вектор указателя на TBullets , приведенного к указ. на IAnimation( (IAnimation*)&TBullets )???
//ПС , точнее его дальнейшее использование !

Автор: mes 27.10.2008, 23:25
вот подправил пример под вашу задачу:
Код

class TAllAnimation
{
    public:
       void Clear() {..};
       void AddAnimations       (TAnimations * p) { ... }
       void RemoveAnimations ( TAnimations * p) { ... }
       void RenderAll  (..) {  for  (std::vector<TAnimations* >::iterator it = m_vAnims.begin(); it!=m_vAnims.end(); ++it)  if (*it) *it->Render(...);  }
    private:
       std::vector<TAnimations* > m_vAnims;
};

TAllAnimation all_anims;
all_anims.Add (new ТBullets);
all_anims.Add (new ТHumans);
all_anims.RenderAll (..);

однако советую разобраться с полиморфизмом, чтоб найти к Вашей задаче наиболее подходящее решение  smile 

Автор: Torsten 28.10.2008, 15:08
Цитата(REZiaMIX @  27.10.2008,  23:19 Найти цитируемый пост)
нужно сделать обобщенный рендер , не в зависимости от класса(при условии наличия у них фции render)

Предлагаю тебе сделать условие, не при наличии фции, а при наследовании определенного класса.
А сделать это очень просто.

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

Фишка в том что в конструкторе этого базового класса (у которого есть виртуальный метод Render) тебе нужно вызвать метод сигнлотона и добавить в этот список этот обьект.
В коде это примерно так должно выглядеть :

Код

class RenderObject
{
public:
      RenderObject() { RenderContainer::Instance().Add(this); }
      void Render() { RenderImpl(); }       

private:
      virtual void RenderImpl() = 0;
};

class RenderContainer : public Singletone<RenderContainer>
{
public:
     void Add(RenderObject * p)
     {
            m_List.push_back(p);
     }
 
     virtual ~RenderContatainer() {  /*очищаем элементы конейнера вручну, или можно std дек заменить на boost::deque_ptr, для автоматичского удаления*/ }

private:
     typedef std::deque<RenderObject*> RenderObjectsList;
    RenderObjectsList  m_List;
};


Ну и класса RenderContainer соотвественно метод, который вызовет через цикл у всех обьектов Render метод Rendor. Все что нужно будет сделать - унаследовать твой обьект от класс RenderObject, определить в нем RenderImpl() и создать этот обьект, он сам добавится в конейнер, причем сделать это можно в любой части программы.

Естественно в синглтон можно и твои глоб. переменные запихнуть, как раз ты сможешь тогда эти переменные передавать методу Render если это будет нужно.

Автор: mes 28.10.2008, 19:09
Цитата(Torsten @  28.10.2008,  15:08 Найти цитируемый пост)
Создаешь класс контейнер - сигнлтон, в котором хранится список всех обьектов которые нужно отредерить - т.е. указатели на базовые класс.

а зачем в данном случае синглетон?  а вобще это плохая тенденция применять патерны где они не нужны, только потому что у них название звучное..

Автор: REZiaMIX 29.10.2008, 14:11
Всем спасибо , буду разбираться!

Автор: Torsten 29.10.2008, 15:51
Цитата(mes @  28.10.2008,  19:09 Найти цитируемый пост)
а зачем в данном случае синглетон?  а вобще это плохая тенденция применять патерны где они не нужны, только потому что у них название звучное..

потому что удобно. Зачем - чтобы иметь возможность доступа к обьекту из любой точки. И насколько я понял обьект этот 1 и смысл создовать таких обьектов более 1 - нету.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)