Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Запутался с наследованием и полиморфизмом 
:(
    Опции темы
mes
Дата 10.11.2010, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



Цитата(Нитонисе @  10.11.2010,  13:28 Найти цитируемый пост)
Напишите. Общую задумку я пока не понимаю. 

вот в общей функции :
Код

void  construction::calc_moments ()
{
// с применением "хака" о знании того,
// что для всех кроме riget moment будет равен 0

  
   struct for_riget : i_load_visitor
   { 
      size_t len;     // bar_length
      size_t s2;      // supports      
      float m1, m2; // moments
   
      
      for_riget ( size_t len_
                , size_t s2_ ) : len (len_)
                               , s2  (s2_)                   
      {
      }
      void operator () (i_load& l) 
      {
         l.accept(*this);
      }
      void visit (linear_load& l)
      {
          using namespace calc_moment;
          switch (s2)
          
          {
              case supports::riget :
              {
                m1 = rrl(len, l.value);
                m2 = m1;
                return;
              }
              case supports::hince :
              {
                m1 = rhl(len, l.value);
                m2 = 0;                
                return;
              }
             case supports::free :
              {
                m1 = rfl(len, l.value);
                m2 = 0;                
                return;
              } 
          }     
       }
       virtual void visit (partlinear_load&l)
       {
       // аналогично linear_load
       }
       virtual void visit (dot_load&l)
       {
       // аналогично linear_load       
       }
         
   };

   if (support[0]==supports::riget)
   {
     for_riget calc(length, support[1]);
     calc (*load);
     moment[0] = calc.m1;
     moment[1] = calc.m2;
   }    
   else if (support[1]==supports::riget)
   {
     for_riget calc(length, support[0]);
     calc (*load);
     moment[1] = calc.m1;
     moment[0] = calc.m2;
   }
   else 
   {
       moment[0] = moment[1] =0;
   }
}

теперь нужно подумать что еще можно "съэкономить"


Это сообщение отредактировал(а) mes - 10.11.2010, 16:07


--------------------
PM MAIL WWW   Вверх
mes
Дата 10.11.2010, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



вот подправлено немного :
Код

void  construction::calc_moments ()
{
// с применением "хака" о знании того,
// что для всех кроме riget moment будет равен 0

  
   struct for_riget : i_load_visitor
   { 
      size_t len;     // bar_length
      size_t sup;      // supports      
      float  m;
   
      
      for_riget ( size_t len_
                , size_t sup_ ) : len (len_)
                                , sup (sup_)                   
      {
      }
      float operator () (i_load& l) 
      {
         l.accept(*this);
         return m;
      }
      void visit (linear_load& l)
      {
          using namespace calc_moment;
          
          typedef float (*fn_t)(size_t, float)

          static  fn_t vt = { &rrl, &rhc, &rfl }; 
          
          if (sup<3)  m = vt[sup] (len, l.value);
  
       }
       virtual void visit (partlinear_load&l)
       {
       
       }
       virtual void visit (dot_load&l)
       {
       
       }
         
   };

   if (support[0]==supports::riget)
   {
     for_riget calc(length, support[1]);   
 
     moment[0] = calc(*load)
  
     if (support[1]==supports::riget)    
       moment[1] = moment[0];     
   }    
   else if (support[1]==supports::riget)
   {
     for_riget calc(length, support[0]);
 
     moment[1] = calc(*load);
     moment[0] = 0;
   }
   else 
   {
       moment[0] = moment[1] =0;
   }
}



Это сообщение отредактировал(а) mes - 10.11.2010, 16:06


--------------------
PM MAIL WWW   Вверх
Нитонисе
Дата 10.11.2010, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(mes @  10.11.2010,  15:24 Найти цитируемый пост)
теперь нужно подумать что еще можно "съэкономить"

Мне вообще-то непонятно - а что вы тут сэкономили то? Закрывая глаза на сложную для восприятия структуру кода можно отметить следующее - суть ее аналогична моей. Вы так же проверяете типы опор и тип нагрузки, запуская те или иные обработчики. Только я не совсем понял одну вещ. Вы проверяете первую опору switch (s2), но не проверяете вторую switch (s2[1]), хотя от этого зависит алгоритм вычислений... 
Вобщем оформление кода - дело субъективного восприятия. Вы не можете читать мой код, я не могу читать ваш код.

Что же касается "красивого" решения вопроса вызывания нужной функции вычисления усилий в зависимости от типов опор и типов нагрузки - смотрю в сторону мультиметодов. Очень интересная тема, надо с ней поподробнее разобраться)
PM MAIL   Вверх
mes
Дата 10.11.2010, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



Цитата(Нитонисе @  10.11.2010,  14:50 Найти цитируемый пост)
Мне вообще-то непонятно - а что вы тут сэкономили то? Закрывая

пока мало чего.. не торопитесь.. я еще не закончил smile

Добавлено через 44 секунды
Цитата(Нитонисе @  10.11.2010,  14:50 Найти цитируемый пост)
Вы проверяете первую опору switch (s2), но не проверяете вторую switch (s2[1]), хотя от этого зависит алгоритм вычислений... 

смотрите внимательно.. проверяются обе.. 
smile

Добавлено через 4 минуты и 21 секунду
возвращаемся к ns_calc_moment и добавляем туда функцию
Код

//a -auto for supports
float rаl (size_t s, size_t l, float v) 
{
    typedef float (*fn_t)(size_t l, float v)
    static vt[3] ={ &rrl, &rhl, &rfl };
    return vt[s](l,v);
}




--------------------
PM MAIL WWW   Вверх
Нитонисе
Дата 10.11.2010, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(mes @  10.11.2010,  15:51 Найти цитируемый пост)
пока мало чего.. не торопитесь.. я еще не закончил

Не трудитесь) Я уже вижу по вашему стилю, что он для меня неприемлем. Масса малопонятных однобуквенных обозначений, сложные программные констркции. Может вы что-то и сэкономите, но такую цену (сложность восприятия) я платить не готов)) Да и вопрос то был нев экономии, а в "грязном" коде. Сэкономить можно проще - просто вынести расчетные блоки в отдельные функции. Для меня не страшно большое количество кода (пусть и разбросанного по разным функциям), для меня важнее его понятность, эффективная работа, удобная модификация.
PM MAIL   Вверх
mes
Дата 10.11.2010, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



Цитата(mes @  10.11.2010,  14:42 Найти цитируемый пост)
   void visit (linear_load& l)
      {
          using namespace calc_moment;
          
          typedef float (*fn_t)(size_t, float)
          static  fn_t vt = { &rrl, &rhc, &rfl }; 
          
          if (sup<3)  m = vt[sup] (len, l.value);
  
       }

тогда станет :
Код

  void visit (linear_load& l)
  {
          m = calc_moment::ral (sup, length, l.value);                
 }


Добавлено через 3 минуты и 23 секунды
чтоб избежать лишнего расчета для rr, придется немножко лишнего кода написать.. 



--------------------
PM MAIL WWW   Вверх
mes
Дата 10.11.2010, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



Цитата(mes @  10.11.2010,  14:42 Найти цитируемый пост)
  if (support[0]==supports::riget)
   {
     for_riget calc(length, support[1]);   
 
     moment[0] = calc(*load)
  
     if (support[1]==supports::riget)    
       moment[1] = moment[0];     
   }    
   else if (support[1]==supports::riget)
   {
     for_riget calc(length, support[0]);
 
     moment[1] = calc(*load);
     moment[0] = 0;
   }
   else 
   {
       moment[0] = moment[1] =0;
   }

после поправки :
Код

   struct helper
   {
      static void calc (size_t len, size_t sup, i_load& load)
      {
         for_riget calc(len, sup);       
         return calc (*load);
      }

   }
    
   if (support[0] == supports::riget)
   {
         moment[0] = helper::calc(length, support[1], *load);        
         moment[1] = (support[1]==support[0])         
                   ?  moment[0] 
                   : 0;
    }         
    else if (support[1]==supports::riget)
    { 
         moment[0] = helper::calc(length, support[1], *load);        
         moment[1] = 0;   
     }
     else
         moment[0] = moment[1] = 0;
 

Это сообщение отредактировал(а) mes - 10.11.2010, 16:51


--------------------
PM MAIL WWW   Вверх
mes
Дата 10.11.2010, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



итак у нас получилась вспомогательная функция :
Код

static float for_riget (size_t len, size_t sup, i_load& load)
{ 
   struct helper : i_load_visitor
   { 
      size_t len;     // bar_length
      size_t sup;      // supports      
      float  m;
         
      helper ( size_t len_ ,  size_t sup_ ): len (len_)  , sup (sup_)  { }

      void operator () (i_load& l)   { l.accept(*this);   }
      void visit (linear_load& l)    { calc_moment::ral (len, l.value);  }
      void visit (partlinear_load&l) { calc_moment::rap (len, ..); }      
      void visit (dot_load&l)        { calc_moment::rad (len, ..); }
         
   };
     
   helper h(len, sup);       
   h (*load);
   return h.m
}

и основная 
Код


void  construction::calc_moments ()
{
// с применением "хака" о знании того,
// что для всех кроме riget moment будет равен 0
    
   if (support[0] == supports::riget)
   {
         moment[0] = for_riget (length, support[1], *load);        
         moment[1] = (support[1]==support[0])         
                   ?  moment[1] 
                   : 0;
    }         
    else if (support[1]==supports::riget)
    { 
         moment[1] = for_riget (length, support[0], *load);        
         moment[0] = 0;   
     }
     else
         moment[0] = moment[1] = 0;   
}


Добавлено @ 16:49
вот к последнему варианту можете придераться smile только не к синтаксическим ошибках, так как писал на коленке smile


Это сообщение отредактировал(а) mes - 10.11.2010, 16:53


--------------------
PM MAIL WWW   Вверх
Нитонисе
Дата 10.11.2010, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(mes @  10.11.2010,  16:46 Найти цитируемый пост)
вот к последнему варианту можете придераться

Да я в общем-то уже "придрался" - код не облегчился и стал сложнее, "заковырестее". Я не вникал в правильность реализации отдельно взятых функций (точнее в определнии верного пути к нужному блоку), так как для меня такие программные конструкции не читаемы, жалко времени. Всущности организация кода должна быть понятна вам и совсем не обязательно, чтобы она была понятно кому-то еще, если только вы не работаете в команде.
PM MAIL   Вверх
mes
Дата 10.11.2010, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



Цитата(Нитонисе @  10.11.2010,  16:10 Найти цитируемый пост)
Да я в общем-то уже "придрался" - код не облегчился и стал сложнее, "заковырестее".

да кода стало чуточку больше.. 
1.  но мы избавились от медленного динамик_каста, 
2. автоматизировалась часть по выбору нужной ветви
3. компилтайм проверка, для всех лоадов, о наличии реализации для конкретного потомка (патерн визитер)
4. все функции расчетники выведены из в отдельную область.. 
(ах да про них забыл.. с учетом последних изменений они должны иметь вид аналогичный : float rrl (size_t len, linear_load& l));
5. в отличие от мултиметодов, для которых еще чуточку кода добавиться, мы использовали "знание о riget"
smile
"заковырестей" он стал для Вас, но зато стал более "сопровождаем" smile
хотя по сути ничего сложного нет, если понять суть на которой он основан smile

Это сообщение отредактировал(а) mes - 10.11.2010, 17:26


--------------------
PM MAIL WWW   Вверх
mes
Дата 10.11.2010, 18:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



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





Это сообщение отредактировал(а) mes - 10.11.2010, 18:06


--------------------
PM MAIL WWW   Вверх
mes
Дата 10.11.2010, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



http://liveworkspace.org/code/36203ae8fe26...a690733c9408081
вот расчет для линейной нагрузки, для произвольного сочетания двух опор..

Добавлено @ 20:06
вместо цифр (3,4,5) соответсвующий расчет разумеется..
ну а main просто для теста.. 

ну и для наглядности выложу тут :
Код

void rrl (float& m1, float& m2, size_t len, linear_load& load)
{
     m1 = 3;     
     m2 = m1;
}
void rhl (float& m1, float& m2, size_t len, linear_load& load)
{
     m1 = 4;
     m2 = 0;
}
void rfl (float& m1, float& m2, size_t len, linear_load& load)
{
     m1 = 5;
     m2 = 0;
}
void nnl (float& m1, float& m2, size_t len, linear_load& load)
{
     m1 =  m2 = 0;
}
void hrl (float& m1, float& m2, size_t len, linear_load& load)
{
   rhl (m2, m1, len, load);
}
void frl (float& m1, float& m2, size_t len, linear_load& load)
{
   rfl (m2, m1, len, load);
}

void aal (float& m1, float& m2
         ,size_t s1, size_t s2          
         ,size_t len, linear_load& load)
{
   typedef void (*fn_t)(float&, float&, size_t, linear_load&);

   static fn_t vt[3][3] = 
   { { &rrl, &rhl, &rfl }
   , { &hrl, &nnl, &nnl }
   , { &frl, &nnl, &nnl }
   };
    
   vt[s1][s2](m1,m2, len, load);
    
}


Это сообщение отредактировал(а) mes - 10.11.2010, 20:54


--------------------
PM MAIL WWW   Вверх
mes
Дата 10.11.2010, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 6
Всего: 250



тогда диспетчер калькулятора будет выглядить так :
Код

void  construction::calc_moments ()
{ 
   struct helper : protected i_load_visitor
   { 
      helper ( construction &cs_ ): cs(cs_) { }  
 
      void calc () {  load.accept(cs.load); }

    protected:
      void visit (linear_load& load)    
      {
        calc_moment::aal ( cs.moment[0],  cs.moment[1]
                         , cs.support[0], cs.support[1]
                         , cs.length, load );                 
      }
      void visit (partlinear_load&l) { /* .. */  }  
      void visit (dot_load&l) {  /* .. */ }

      construction & cs;
   };

   helper h(*_this);
   h.calc();
}


Добавлено @ 20:40
или для вашего стиля  (с динамик кастом )
Код

void  construction::calc_moments ()
{ 
   if  (auto * pload = dynamic_cast<linear_load*> (this->load) )
   { 
        calc_moment::aal ( cs.moment[0],  cs.moment[1]
                         , cs.support[0], cs.support[1]
                         , cs.length, *pload );                 
   }
   else
   if  (auto * pload = dynamic_cast<partlinear_load*> (this->load) )
   { 
        calc_moment::aap ( .. );
   }
   else
   if  (auto * pload = dynamic_cast<dot_load*> (this->load) )
   { 
        calc_moment::aad ( .. );                 
   }

}

P.S. если auto не поддерживается, значит вместо него соответсвующий тип.. 

оба варианта практически равноправны.. первый чуточку быстрей, а с динамик_кастом чуточку проще.. 
выбирайте на свой вкус.. если что то осталось непонятное,  могу объяснить smile


Это сообщение отредактировал(а) mes - 10.11.2010, 20:53


--------------------
PM MAIL WWW   Вверх
baldina
Дата 11.11.2010, 10:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 1
Всего: 101



ребят, тут поглядите
PM MAIL   Вверх
Нитонисе
Дата 11.11.2010, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 917
Регистрация: 5.11.2009

Репутация: 2
Всего: 2



Цитата(baldina @  11.11.2010,  10:42 Найти цитируемый пост)
ребят, тут поглядите

Мультиметоды нравятся, но не могу разобраться с их реализацией. Есть хороший ресурс на русском языке с мельчайшим разжевыванием?  smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0719 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.