OLP. Problemi di applicazione - pagina 8

 
Interesting:

1. La funzionalità discendente non è disponibile. Non so chi o come, ma personalmente non ho mai avuto accesso a SetRadius() e SetSide() dall'Array.Forse c'è un modo per risolvere il problema con autogenous, ma voglio farne a meno.

2. Forse sto lavorando male con i puntatori, ma o ho una perdita per tutto il tempo o devo colpire i puntatori proprio nel blocco dove viene fatto il lavoro principale.

Tutti disponibili... il mio post sopra
 
equivalent23:

Posso fare un esempio?

È solo che l'esempio che ho dato è stato preso dalla documentazione e non è chiaro come dovrebbe funzionare...

Ecco come funziona. Ma completamente fuori dalla documentazione :/ (Ma ancora una volta mi sono esercitato sui puntatori)

#property copyright "Ya"
#property link      "Ya"
#property version   "1.00"
//--- Базовый класс
class CShape
  {
protected:
   int               m_type;                // тип фигуры
   int               m_xpos;                // X - координата точки привязки
   int               m_ypos;                // Y - координата точки привязки
public:
   void           CShape(){m_type=0;};   // конструктор, тип равен нулю
   int            GetType(){return(m_type);};// возвращает тип фигуры
   virtual void           SetRadius(double r){return;};
   virtual void           SetSide(double s){return;};
   virtual double         GetArea(){return(0); }// возвращает площадь фигуры
  };
//--- производный класс Круг
class CCircle: public CShape          // после двоеточия указывается базовый класс,
  {                                      // от которого производится наследование 
private:
   double            m_radius;              // радиус круга

public:
   void           CCircle(){m_type=1; m_radius=10;};  // конструктор, тип равен 1 
   virtual void           SetRadius(double r){m_radius=r;};
   virtual double GetArea(){return(3.14*m_radius*m_radius);}// площадь круга
  };
//--- производный класс Квадрат
class CSquare: public CShape          // после двоеточия указывается базовый класс,
  {                                      // от которого производится наследование 
private:
   double            m_square_side;        // сторона квадрата

public:
   void            CSquare(){m_type=2;}; // конструктор, тип равен 2 
   virtual void            SetSide(double s){m_square_side=s;};
   virtual double GetArea(){return(m_square_side*m_square_side);}//площадь квадрата
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   CCircle *ci=new CCircle;
   CSquare *sq=new CSquare;
   CShape  *shapes[2];                       // массив объектов CShape

   shapes[0]=ci;
   shapes[1]=sq;
////---зададим уникальные свойства объектов
   shapes[0].SetRadius(5.0);
   shapes[1].SetSide(4.0);
   for(int i=0; i<2;i++)
     {
      //--- тип и площадь фигуры
      Print("Объект типа "+shapes[i].GetType()+" имеет площадь "+shapes[i].GetArea());
     }
 
AlexSTAL:

Eseguire:

può essere fatto molto più semplicemente... virtualizzazione:


Non è di questo che sto parlando. Non stiamo parlando di usare semplicemente dei puntatori, stiamo parlando di un array di questi puntatori con un tipo di classe base.

CShape ArrShapes[10]; // массив объектов CShape

Non importa se è un semplice array o un array di puntatori, solo ciò che è scritto nella classe base funziona ed è disponibile.

O forse mi manca qualcosa.

Per esempio, una classe base leggermente modificata (progettata come struttura)

//class CShape
struct CShape
//Базовый класс
{  
protected: 
int            m_type;                // тип фигуры
int            m_xpos;                // X - координата точки привязки
int            m_ypos;                // Y - координата точки привязки

public:
void           CShape(){m_type=0;};   // конструктор, тип равен нулю
int            GetType(){return(m_type);};// возвращает тип фигуры

void           SetPosX(int s){m_xpos=s;};
int            GetPosX(){return(m_xpos);};

void           SetPosY(int s){m_ypos=s;};
int            GetPosY(){return(m_ypos);};

double GetArea(){return (0); }// возвращает площадь фигуры

};

Se stipiamo tutta questa roba nell'array, avremo accesso almeno alle funzionalità dichiarate nella classe base.

La domanda è come accedere alla funzionalità per discendente se l'array è di tipo di classe base (cioè l'array è di tipo CShape)?

Когда нужно использовать указатели в MQL5
Когда нужно использовать указатели в MQL5
  • 2010.03.25
  • MetaQuotes Software Corp.
  • www.mql5.com
Все объекты в MQL5 по умолчанию передаются по ссылке, но есть возможность использовать и указатели объектов. При этом есть опасность получить в качестве параметра функции указатель неинициализированного объекта. В этом случае работа программы будет завершена критически с последующей выгрузкой. Автоматически создаваемые объекты как правило такой ошибки не вызывают, и в этом отношении они достаточно безопасны. В этой статье мы попробуем разобраться в чем разница между ссылкой и указателей, когда оправдано использование указателей и как написать безопасный код с использованием указателей.
 
Interesting:

Non è di questo che sto parlando. Non stiamo parlando di usare semplicemente dei puntatori, ma di un array di questi puntatori con un tipo di classe base.

La domanda è come accedere alla funzionalità da un discendente se l'array è di tipo classe base (cioè l'array è di tipo CShape)?

Ho scritto nell'ultima pagina come:

class CBase
  {
public:
   void m_radius() {Print("CBase");}
  };

class CTest : public CBase
  {
public:
   void m_radius() {Print("CTest");}
  };

CBase* Base;

void OnStart()
  {
   Base = new CTest;
   Base.m_radius();
   ((CTest *)Base).m_radius();
   delete Base;
  }
 

Stesso codice, solo con un array:

class CBase
  {
public:
   void m_radius() {Print("CBase");}
  };

class CTest : public CBase
  {
public:
   void m_radius() {Print("CTest");}
  };

CBase* Base[1];

void OnStart()
  {
   Base[0] = new CTest;
   Base[0].m_radius();
   ((CTest *)Base[0]).m_radius();
   delete Base[0];
  }
 
Yedelkin:

È così che funziona. Ma completamente fuori dalla documentazione :/

Beh, voglio dire la stessa cosa, dovresti almeno designare tutte le funzioni in una classe base (altrimenti non saranno accessibili).
 
AlexSTAL:

Eseguire:

Per qualcosa del genere:

((CTest *)Base).m_radius();

dovrebbe essere strappato con la confisca della tastiera.

In C++, ci si può muovere attraverso la gerarchia delle classi con dynamic_cast, che non piace neanche lì. In MQL, può causare crash impliciti che non possono essere facilmente risolti, perché il bug è in un posto completamente diverso.

Pertanto, sconsiglio vivamente di usare questo tipo di conversione. Cioè, a tutti. Agli antenati per favore, ai bambini ni.

 
TheXpert:

Per qualcosa del genere:

Dovresti togliere le mani e farti confiscare la tastiera.

In C++, ci si può muovere attraverso la gerarchia delle classi usando dynamic_cast, e anche lì non piace. In MQL può causare crash impliciti che non possono essere facilmente risolti, perché il bug è in un posto completamente diverso.

Pertanto, sconsiglio categoricamente di usare una tale conversione. Cioè, per niente. Agli antenati per favore, non ai bambini.

Qual è il modo educato di rispondere....

Se il programmatore è troppo stupido, allora una semplice operazione 1+1 può causare crash impliciti....

E voglio sottolineare che MQL5 non è C++...

Questa è solo una possibilità, non una questione di applicazione....

 
AlexSTAL:

Stesso codice, solo con un array:


1. Rimuovere m_radius() dall'antenato, non è nell'esempio. :) E non otterrete alcun lavoro con esso in OnStart();

2. la linea delete Base[0] può essere spostata da qualche altra parte? Diciamo, se non è uno script ma un gufo e ho ancora bisogno dei dati nell'array.

Ho subito delle perdite di memoria. Ho dovuto passare alle strutture per questo motivo...

 
Interesting:

1. Rimuovere m_radius(), non è presente nell'esempio. E non ottenere alcun lavoro con esso in OnStart();

2. posso spostare la linea delete Base[0] da qualche altra parte? Diciamo, se non è uno script ma un gufo, e ho ancora bisogno dei dati nell'array.

Ho subito una perdita di memoria. Ho dovuto passare alle strutture per questo motivo...

1) Rimosso, funziona:

class CBase
  {
public:
  };

class CTest : public CBase
  {
public:
   void m_radius() {Print("CTest");}
  };

CBase* Base[1];

void OnStart()
  {
   Base[0] = new CTest;
   ((CTest *)Base[0]).m_radius();
   delete Base[0];
  }
2) L'importante è cancellarlo prima che il programma finisca... Ma se avete questo puntatore creato in una funzione, dovete preoccuparvi di salvarlo in un posto globale...
Motivazione: