PLO. Fragen zur Anwendung - Seite 8

 
Interesting:

1. Die Funktionalität der Nachkommenschaft ist nicht verfügbar. Ich weiß nicht, wer oder wie, aber ich persönlich habe nie Zugriff auf SetRadius() und SetSide() aus dem Array.Vielleicht gibt es einen Weg, um das Problem mit Autogenous zu lösen, aber ich möchte ohne sie zu tun.

2. Vielleicht arbeite ich falsch mit Zeigern, aber ich habe entweder immer ein Leck oder muss die Zeiger genau in dem Block treffen, in dem die Hauptarbeit geleistet wird.

Alle verfügbaren... mein obiger Beitrag
 
equivalent23:

Darf ich Ihnen ein Beispiel nennen?

Es ist nur so, dass das Beispiel, das ich gegeben habe, aus der Dokumentation stammt und es nicht klar ist, wie es funktionieren soll...

Das funktioniert folgendermaßen. Aber völlig aus der Dokumentation :/ (Aber ich habe wieder einmal mit Zeigern geübt)

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

Ausführen:

kann viel einfacher gemacht werden... Virtualisierung:


Das ist nicht das, was ich meine. Es geht nicht nur um die Verwendung von Zeigern, sondern um ein Array von Zeigern mit einem Basisklassentyp.

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

Es spielt keine Rolle, ob es sich um ein einfaches Array oder ein Array mit Zeigern handelt, es funktioniert nur das, was in der Basisklasse steht.

Oder vielleicht übersehe ich etwas.

Zum Beispiel eine leicht veränderte Basisklasse (als Struktur konzipiert)

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

};

Wenn wir all diese Dinge in das Array packen, haben wir zumindest Zugriff auf die in der Basisklasse deklarierten Funktionen.

Die Frage ist, wie der Zugriff auf Funktionalität durch Nachkomme, wenn das Array der Basisklasse Typ ist (d.h. Array ist von CShape Typ)?

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

Das ist nicht das, wovon ich spreche. Es geht nicht um die einfache Verwendung von Zeigern, sondern um ein Array dieser Zeiger mit einem Basisklassentyp.

Die Frage ist, wie man auf die Funktionalität durch einen Nachkommen zugreifen kann, wenn das Array vom Typ der Basisklasse ist (d.h. das Array ist vom Typ CShape)?

Ich habe auf der letzten Seite geschrieben, wie:

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

Gleicher Code, nur mit einem 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:

So funktioniert es. Aber völlig abseits der Dokumentation :/

Nun, ich meine das Gleiche, man sollte zumindest alle Funktionen in einer Basisklasse benennen (sonst sind sie nicht zugänglich).
 
AlexSTAL:

Ausführen:

Für etwas wie dieses:

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

sollte mit der Beschlagnahmung der Tastatur aufgehoben werden.

In C++ kann man sich mit dynamic_cast durch die Klassenhierarchie bewegen, und auch dort ist es nicht beliebt. In MQL kann es zu impliziten Abstürzen kommen, die nicht leicht zu beheben sind, weil der Fehler an einer ganz anderen Stelle liegt.

Daher rate ich dringend davon ab, diese Art der Umwandlung zu verwenden. Das heißt, überhaupt nicht. Für die Vorfahren bitte, für die Kinder ni.

 
TheXpert:

Für etwas wie dieses:

sollte man Ihnen die Hände abnehmen und die Tastatur konfiszieren.

In C++ können Sie sich mit dynamic_cast durch die Klassenhierarchie bewegen, und auch dort ist es nicht beliebt. In MQL kann es zu impliziten Abstürzen kommen, die nicht leicht zu beheben sind, weil der Fehler an einer ganz anderen Stelle liegt.

Daher rate ich kategorisch davon ab, eine solche Umwandlung vorzunehmen. Das heißt, ganz und gar nicht. An die Vorfahren bitte, nicht an die Kinder.

Wie lautet die höfliche Antwort an....

Wenn der Programmierer zu dumm ist, dann kann eine einfache 1+1-Operation zu impliziten Abstürzen führen....

Und ich möchte darauf hinweisen, dass MQL5 nicht C++ ist...

Dies ist nur eine Möglichkeit, keine Frage der Bewerbung....

 
AlexSTAL:

Gleicher Code, nur mit einem Array:


1. Entfernen Sie m_radius() aus dem Vorgänger, es ist nicht im Beispiel enthalten. :) Und Sie werden in OnStart() keine Arbeit damit haben;

2. Kann die Zeile delete Base[0] an eine andere Stelle verschoben werden? Nehmen wir an, es handelt sich nicht um ein Skript, sondern um eine Eule, und ich benötige trotzdem die Daten im Array.

Ich habe sofort Speicherlecks. Aus diesem Grund musste ich zu Strukturen wechseln...

 
Interesting:

1. Entfernen Sie m_radius(), es ist in dem Beispiel nicht vorhanden. Und in OnStart() keine Arbeit damit bekommen;

2. Kann ich die Zeile delete Base[0] an eine andere Stelle verschieben? Nehmen wir an, es handelt sich nicht um ein Skript, sondern um eine Eule, und ich benötige trotzdem die Daten im Array.

Ich habe sofort ein Speicherleck. Aus diesem Grund musste ich zu Strukturen wechseln...

1) Entfernt, es funktioniert:

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) Das Wichtigste ist, sie zu löschen, bevor das Programm endet... Wenn Sie diesen Zeiger jedoch in einer Funktion erstellt haben, müssen Sie dafür sorgen, dass er an einem globalen Ort gespeichert wird...