Domande su OOP (programmazione orientata agli oggetti) - pagina 7

 
Zhunko:

Vasily, un esempio, per favore!

Conosco solo un caso in cui dovete allocare la memoria e avete bisogno di un puntatore ad essa.

Sono sicuro che puoi quasi sempre farne a meno. È auspicabile non usare la gestione manuale della memoria. C'è sempre una libreria standard che ha già risolto questi problemi.


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:
La presenza di identificazione dinamica del tipo di solito indica l'architettura stampella di un progetto.


La presenza dell'identificazione dinamica dei tipi indica un alto grado di polimorfismo e un livello più alto di astrazione. Aumenta la gestibilità e la scalabilità del progetto. Permette di lavorare con il codice a livello di interfaccia e incoraggia il programmatore a non entrare nei dettagli dell'implementazione.
 
Vasily, penso che il tuo esempio sia fuori luogo. Ci sono modelli (macro in µl), che possono risolvere molti problemi al momento della compilazione. E se dovete fare la down-conversion, non avete progettato bene il programma (lo ha detto anche Straustrup).
 
Pavlick:
Vasily, penso che il tuo esempio sia fuori luogo. Ci sono dei template (macro in µl), che possono risolvere molti problemi in fase di compilazione. E se dovete fare la down-conversion, avete progettato male il programma (lo ha detto anche Straustrup).

Cosa c'è di sbagliato nel cambio al ribasso con un controllo rigoroso del tipo? Straustrup ha detto questo quando non c'era nessun tipo di controllo. Ora, se conoscete il tipo derivato, potete garantire la conversione prima che inizi e quindi evitare errori di esecuzione.

Ma i vantaggi della down-conversion sono evidenti. Il principale è che funziona a livello di interfaccia. Se il costruttore di una classe base è chiuso nell'ambito protetto, è un'interfaccia e una classe astratta e possiamo lavorare con essa al suo livello senza dover conoscere l'implementazione raffinata dei suoi discendenti. Ma se implementiamo un comportamento polimorfico a seconda del tipo di istanza, possiamo sicuramente specificare l'implementazione dell'istanza corrispondente e ad esempio chiamare il suo metodo unico. Con le funzioni virtuali non avremo nemmeno bisogno della conversione dei tipi. Dopo tutto, le funzioni virtuali chiameranno l'implementazione specifica "dietro le quinte".

 
C-4:

... Con le funzioni virtuali, anche una conversione di tipo non sarà necessaria. Dopo tutto, le funzioni virtuali chiameranno una particolare implementazione "dietro le quinte".


Non ho nulla contro quello evidenziato. Hai avuto un approccio diverso nell'esempio.
C-4:

Cosa c'è di sbagliato nel cast cadente quando i tipi sono strettamente controllati?

Se lo scrivi correttamente, non ne hai bisogno.

P.S: non sto mettendo nella stessa bottiglia l'identificazione del tipo samapal e il meccanismo della funzione virtuale.

 

Un esempio da una vera applicazione MQL:

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

Mi piacerebbe sentire le opinioni degli esperti su come risolverebbero un tale problema. Personalmente l'ho risolto usando l'identificazione dinamica del tipo, il metodo "pattern" e le conversioni step-down. È stato risolto così bene che finalmente mi ha permesso di creare complesse tabelle interattive con elementi irregolari e completamente personalizzabili. I risultati sono così tangibili che trovo ingenuo affermare che de "l'identificazione dinamica è una stampella" e "la down-conversion è il male".

p.s. Pavlick, a proposito, non hai ancora risposto a cosa c'è esattamente di sbagliato nella down-conversion.

 

No, sono lontano dall'essere un esperto. Quello che ho detto sul riduttore è la mia esperienza, mi sforzo di scriverlo così + è confermato da persone che rispetto. Scrivere un programma per dimostrare qualcosa è una perdita di tempo.

Pavlick, a proposito, non hai ancora risposto a cosa esattamente rende cattivo il ridimensionamento.

È difficile da spiegare. Capisco, ma non posso dirlo). I libri probabilmente lo spiegheranno meglio.

 
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;
      }
   }
}

Anche se non è un errore, ci sono modelli e typeid().
 
Pavlick:

No, sono lontano dall'essere un esperto.

Ma Stroustrup lo è. E anche molti altri. Stai dicendo tutte le cose giuste.
 
Typeid() purtroppo non esiste, e la forza dei template è l'identificazione statica. Problemi diversi si risolvono con metodi diversi e dire che un metodo è cattivo e l'altro è buono è un presupposto sbagliato.
Motivazione: