OLP. Problemas de aplicación - página 8

 
Interesting:

1. La funcionalidad de los descendientes no está disponible. No sé quién o cómo, pero personalmente nunca he conseguido acceder a SetRadius() y SetSide() desde el Array.Quizás haya una forma de solucionar el problema con autogenous, pero quiero prescindir de él.

2. Tal vez estoy trabajando incorrectamente con los punteros, pero o bien tengo una fuga todo el tiempo o tengo que golpear los punteros justo en el bloque donde se realiza el trabajo principal.

Todos los disponibles... mi post anterior
 
equivalent23:

¿Puedo darle un ejemplo?

Es que el ejemplo que he puesto está sacado de la documentación y no está claro cómo debería funcionar...

Así es como funciona. Pero completamente sin documentación :/ (Pero una vez más he practicado con punteros)

#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:

Ejecutar:

puede hacerse de forma mucho más sencilla... virtualización:


No me refiero a eso. No estamos hablando de usar simplemente punteros, estamos hablando de un array de estos punteros con un tipo de clase base.

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

No importa si es un simple array o un array de punteros, sólo lo que está escrito en la clase base funciona y está disponible.

O quizás me estoy perdiendo algo.

Por ejemplo, una clase base ligeramente modificada (diseñada como una estructura)

//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); }// возвращает площадь фигуры

};

Si metemos todo esto en el array, tendremos acceso al menos a la funcionalidad declarada en la clase base.

La pregunta es cómo acceder a la funcionalidad por descendiente si el array es de tipo de clase base (es decir, el array es de tipo CShape).

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

no es eso de lo que estoy hablando. No estamos hablando de usar simplemente punteros, sino de un array de estos punteros con un tipo de clase base.

La cuestión es cómo acceder a la funcionalidad por parte de un descendiente si el array es de tipo de clase base (es decir, el array es de tipo CShape).

He escrito en la última página cómo:

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

El mismo código, sólo que 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:

Así es como funciona. Pero completamente fuera de la documentación :/

Bueno, me refiero a lo mismo, al menos deberías designar todas las funciones en una clase base (si no, no serán accesibles).
 
AlexSTAL:

Ejecutar:

Por algo así:

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

debería ser arrancado con la confiscación del teclado.

En C++ puedes moverte a través de la jerarquía de clases con dynamic_cast, y ahí tampoco te gusta. En MQL, puede provocar fallos implícitos que no se pueden resolver fácilmente, porque el fallo está en un lugar completamente diferente.

Por lo tanto, desaconsejo encarecidamente el uso de este tipo de conversión. Es decir, en absoluto. A los ancestros por favor, a los niños ni.

 
TheXpert:

Por algo así:

deberían quitarte las manos y confiscarte el teclado.

En C++, puedes moverte a través de la jerarquía de clases usando dynamic_cast, y tampoco te gusta allí. En MQL puede provocar fallos implícitos que no se pueden resolver fácilmente, porque el fallo está en un lugar completamente diferente.

Por lo tanto, desaconsejo categóricamente el uso de dicha conversión. Es decir, en absoluto. A los ancestros por favor, no a los niños.

¿Cuál es la forma educada de responder? ....

Si el programador es demasiado tonto, una simple operación de 1+1 puede provocar choques implícitos....

Y quiero señalar que MQL5 no es C++...

Esto es sólo una posibilidad, no una cuestión de aplicación....

 
AlexSTAL:

El mismo código, sólo que con un array:


1. Quita m_radio() del ancestro, no está en el ejemplo. :) Y no conseguirás trabajar con él en OnStart();

2. ¿se puede trasladar la línea de borrado de Base[0] a otro lugar? Digamos que si no es un script sino un búho y todavía necesito los datos del array.

Tengo fugas de memoria de inmediato. Tuve que cambiar a estructuras por esta razón...

 
Interesting:

1. Eliminar m_radio(), no está presente en el ejemplo. Y no se consigue trabajar con él en OnStart();

2. ¿puedo mover la línea de eliminación de Base[0] a otro lugar? Digamos que si no es un script sino un búho, y todavía necesito los datos del array.

Tengo una fuga de memoria de inmediato. Tuve que cambiar a estructuras por esta razón...

1) Eliminado, funciona:

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) Lo principal es borrarlo antes de que termine el programa... Pero si tienes este puntero creado en una función, tienes que ocuparte de guardarlo en una ubicación global...