Вопросы по ООП (Объектно Ориентированному Программированию ) - страница 7

 
Zhunko:

Василий, пример, пожалуйста!

Знаю только один случай, когда необходимо выделять память и нужен указатель на неё.

Уверен, что можно почти всегда обойтись без этого. Желательно не использовать ручное управление памятью. Всегда есть стандартная библиотека, где эти вопросы уже решены.


enum ENUM_CLASS_TYPE
{
   CLASS_PARENT,
   CLASS_CHILD_1,
   CLASS_CHILD_2
};

class Parent
{
   public:
      ENUM_CLASS_TYPE(void){return classType;}
      virtual string GetName(){return "Base";}
   protected:
      Parent(ENUM_CLASS_TYPE type){classType = type;}
   private:
      ENUM_CLASS_TYPE classType;
};

class Child1 : public Parent
{
   public:
      Child1() : Parent(CLASS_CHILD_1){;}
      void MethodChild1(){;}
};

class Child2 : public Parent
{
   public:
      Child2() : Parent(CLASS_CHILD_2){;}
      void MethodChild2(){;}
};

int Start()
{
   Parent* parent = new Child1();
   switch(parent.GetType())
   {
      case CLASS_CHILD_1:
      {
          Child1* ch = parent;
          ch.MethodChild2();
          break;
      }
      case CLASS_CHILD_2:
      {
          Child1* ch = parent;
          ch.MethodChild2();
          break;
      }
   }
}
 
TheXpert:
Наличие динамической идентификации типов обычно говорит о костыльной архитектуре проекта.


Наличие динамической идентификации типов говорит о высокой степени полиморфизма и более высоком уровне абстракции. Повышает управляемость и масштабируемость проекта. Позволяет работать с кодом на уровне интерфейсов и поощряет программиста не вдаваться в подробности реализации.
 
Василий, по-моему ваш пример оторван от жизни. Есть шаблоны (макросы в мкл), они могут решить массу вопросов на стадии компиляции. А если вам приходится делать понижающее приведение - вы плохо спроектировали программу (об этом даже Страуструп говорил).
 
Pavlick:
Василий, по-моему ваш пример оторван от жизни. Есть шаблоны (макросы в мкл), они могут решить массу вопросов на стадии компиляции. А если вам приходится делать понижающее приведение - вы плохо спроектировали программу (об этом даже Страуструп говорил).

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

А вот плюсы понижающего приведения очевидны. Основной - эта работа на уровне интерфейсов. Если конструктор базового класса закрыт в области protected, то он - интерфейс и абстрактный класс и мы можем работать с ним на его уровне без необходимости знать уточняющую реализацию потомков. Но если мы реализуем полиморфное поведение в зависимости от типа экземпляра, то гарантированно можем уточнить реализацию соответствующего экземпляра и например вызвать только ему присущий метод. С функциями virtual даже приведение типов не потребуется. Ведь виртуальные функции вызовут конкретную реализацию "за кулисами".

 
C-4:

... С функциями virtual даже приведение типов не потребуется. Ведь виртуальные функции вызовут конкретную реализацию "за кулисами".


Против выделенного ничего не имею. В примере вы ведь избрали другой подход.
C-4:

Чем понижающее приведение при строгом контроле типов плохо? ...

Если писать правильно, то этого просто не нужно.

P.S: я не объединяю самапальную идентификацию типов и механизм виртуальных функций в один флакон.

 

Пример из реального приложения на MQL:

Дана строка таблицы состоящая из ячеек нескольких типов. Часть из них являются обычным полями текста OBJ_TEXT, часть - кнопками OBJ_BUTTON а часть - ячейками, в которых текст можно редактировать (OBJ_EDIT). Значения введенное в ячейку типа OBJ_EDIT запоминается, и в случае его корректности формируется некий приказ, который отправляется на выполнение внешней системе. В промежутке времени между отправкой приказа и получения ответа от системы необходимо заблокировать строку таблицы таким образом, что бы все ячейки с возможностью редактирования в них текста больше не позволяли вводить в них текст. Все кнопки входящие в строку таблицы не позволяли нажимать на себя, а в целом, все ячейки в которых есть текст, должны были бы изменить его цвет на красный, сигнализируя тем самым о своей блокировке. Строки входящие в таблицу не идентичны друг другу и не содержат регулярной структуры. Одна строка может содержать кнопку, тогда как другая нет. Одна строка может содержать какой-либо столбец, а другая нет и т.д.

Хотелось бы услышать мнения экспертов, как бы они стали решать подобную задачу. Лично мной она была решена с помощью динамической идентификации типов, паттерна "шаблонный метод" и понижающих преобразований. Решена она была на столько хорошо, что в итоге позволила создавать сложные интерактивные таблицы с нерегулярными, полностью настраиваемыми элементами. Результаты настолько ощутимы, что мне кажется наивным утверждения что де "динамическая идентификация - это костыль", а "понижающее преведение - есть зло".

p.s. Pavlick, Вы кстати так и не ответили, чем же конкретно плохо понижающее приведение.

 

Что вы, я далеко не эксперт. То что я сказал про понижающее приведение - мой опыт, я стремлюсь писать именно так + это подтверждают уважаемые мной люди. Писать программу чтобы чего-то доказать, мне жалко своего времени.

Pavlick, Вы кстати так и не ответили, чем же конкретно плохо понижающее приведение.

Сложно объяснить. Понимаю, а сказать не могу )). В книгах, наверное, объяснят лучше.

 
C-4:
enum ENUM_CLASS_TYPE
{
   CLASS_PARENT,
   CLASS_CHILD_1,
   CLASS_CHILD_2
};

class Parent
{
   public:
      ENUM_CLASS_TYPE(void){return classType;}
      virtual string GetName(){return "Base";}
   protected:
      Parent(ENUM_CLASS_TYPE type){classType = type;}
   private:
      ENUM_CLASS_TYPE classType;
};

class Child1 : public Parent
{
   public:
      Child1() : Parent(CLASS_CHILD_1){;}
      void MethodChild1(){;}
};

class Child2 : public Parent
{
   public:
      Child2() : Parent(CLASS_CHILD_2){;}
      void MethodChild2(){;}
};

int Start()
{
   Parent* parent = new Child1();
   switch(parent.GetType())
   {
      case CLASS_CHILD_1:
      {
          Child1* ch = parent;
          ch.MethodChild2(); // Это не ошибка?
          break;
      }
      case CLASS_CHILD_2:
      {
          Child1* ch = parent;// Это не ошибка?

          ch.MethodChild2();
          break;
      }
   }
}

Даже, если это не ошибка, есть шаблоны и typeid().
 
Pavlick:

Что вы, я далеко не эксперт.

Зато Страуструп эксперт. И многие другие тоже. Вы все правильно говорите.
 
Typeid() к сожалению нет, а сила шаблонов в статической идентификации. Разные задачи решаются разными методами и говорить что один метод бяка, а другой хорош - агульное допущение.
Причина обращения: