OLP. Questões de aplicação - página 8

 
Interesting:

1. A funcionalidade descendente não está disponível. Não sei quem ou como, mas pessoalmente nunca tive acesso a SetRadius() e SetSide() do Array.Talvez haja uma forma de resolver o problema com o autogénero, mas quero passar sem ele.

2. Talvez esteja a trabalhar incorrectamente com apontadores, mas ou tenho uma fuga a toda a hora ou tenho de acertar nos apontadores mesmo no bloco onde é feito o trabalho principal.

Todos disponíveis... o meu posto acima
 
equivalent23:

Posso dar-vos um exemplo?

É que o exemplo que dei foi retirado da documentação e não está claro como deve funcionar...

É assim que funciona. Mas completamente sem documentação :/ (Mas, mais uma vez, pratiquei em apontadores)

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

Executar:

pode ser feito muito mais simplesmente... a virtualização:


Não é disso que estou a falar. Não estamos a falar apenas de usar apontadores, estamos a falar de um conjunto destes apontadores com um tipo de classe base.

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

Não importa se é uma simples matriz ou um conjunto de indicadores, apenas o que está escrito na classe base funciona e está disponível.

Ou talvez me esteja a escapar alguma coisa.

Por exemplo, uma classe base ligeiramente modificada (concebida como uma estrutura)

//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 enfiarmos todo este material na matriz, teremos acesso a pelo menos a funcionalidade declarada na classe base.

A questão é como aceder à funcionalidade por descendente se o array é do tipo de classe base (ou seja, array é do tipo CShape)?

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

não é disso que estou a falar. Não estamos a falar de simplesmente usar apontadores, mas de um conjunto destes apontadores com um tipo de classe base.

A questão é como aceder à funcionalidade por um descendente se o array é do tipo de classe base (ou seja, o array é do tipo CShape)?

Escrevi na última página como:

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

O mesmo código, apenas com uma matriz:

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:

É assim que funciona. Mas completamente fora da documentação :/

Bem, quero dizer a mesma coisa, deve pelo menos designar todas as funções de uma classe base (caso contrário, não serão acessíveis).
 
AlexSTAL:

Executar:

Para algo como isto:

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

deve ser arrancado com a confiscação do teclado.

Em C++, pode mover-se através da hierarquia de classes com dynamic_cast, que também não é apreciada lá. Na MQL, pode causar falhas implícitas que não podem ser facilmente resolvidas, porque o bug está num lugar completamente diferente.

Por conseguinte, desaconselho vivamente a utilização deste tipo de conversão. Isto é, de todo. Aos antepassados, por favor, às crianças ni.

 
TheXpert:

Para algo como isto:

deve tirar as mãos e ter o teclado confiscado.

Em C++, pode mover-se através da hierarquia de classes usando o dynamic_cast, e também não é apreciado lá. Na MQL pode causar falhas implícitas que não podem ser facilmente resolvidas, porque o bug está num lugar completamente diferente.

Por conseguinte, desaconselho categoricamente a utilização de tal conversão. Isto é, de modo algum. Aos antepassados, por favor, não às crianças.

Qual é a forma educada de responder....

Se o programador for demasiado burro, então uma simples operação 1+1 pode causar falhas implícitas....

E quero salientar que a MQL5 não é C+++...

Isto é apenas uma possibilidade, não uma questão de aplicação....

 
AlexSTAL:

O mesmo código, apenas com uma matriz:


1. Remover m_radius() do antepassado, não está no exemplo. :) E não terá trabalho com ele em OnStart();

2. Existe algum outro lugar onde se possa colocar a linha de apagar Base[0]? Digamos, se não for um guião mas uma coruja e eu ainda preciso dos dados na matriz.

Tenho fugas de memória de imediato. Por esta razão, tive de mudar para estruturas.

 
Interesting:

1. Remover m_radius(), não está presente no exemplo. E não trabalhar com ele em OnStart();

2. posso mover a linha de apagar Base[0] para outro lugar? Digamos, se não for um guião mas uma coruja, e eu ainda preciso dos dados na matriz.

Tive imediatamente uma fuga de memória. Tive de mudar para estruturas por esta razão...

1) Removido, 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) O principal é apagá-lo antes do fim do programa. Mas se tiveres este ponteiro criado numa função, tens de te ocupar de o guardar num lugar global...