Fragen zu OOP in MQL5 - Seite 67

 

Hier ist eine weitere Frage, hier ist derWiki-Artikel Abstract Class

Ich bin an einem C++-Beispiel interessiert

class CA { // Абстрактный класс
  public:
    CA ( void ) { std::cout << "This object of the class "; }

    virtual void Abstr ( void ) = 0; // Чистая (пустая) виртуальная функция.
    void         fun   ( void ) { std::cout << "Реализация не будет наследоваться!"; }

    ~CA () { std::cout << "." << std::endl; } //Вызывается в обр. порядке конструкторов
  };

class CB : public CA {
  public:
    CB ( void ) { std::cout << "CB;"; }

    void Abstr ( void ){ std::cout << " call function cb.Abstr();"; } //Подменяющая функция.
    void fun   ( void ){ std::cout << " call function cb.fun()"; }

    ~CB () {} // Неверно для абстр. кл. ~CB(){ ~CA(); } 
  };

class CC : public CA {
  public:
    CC ( void ) { std::cout << "CC;"; }

    void Abstr ( void) { std::cout << " call function cc.Abstr();"; } //Подменяющая функция.
    void fun   ( void ) { std::cout << " call function cc.fun()"; }

  ~CC () {} // Неверно для абстр. кл. ~CC(){ ~CA(); } 
  };

int main () {
  std::cout << "Program:" << std::endl;
  CB cb;
  cb.Abstr(); cb.fun(); cb.~CB();

  CC cc;
  cc.Abstr(); cc.fun(); cc.~CC();

  return 0;
  }

Das Ergebnis des Programms:

Programm:

Dieses Objekt der Klasse CB; Funktion cb.Abstr() aufrufen; Funktion cb.fun() aufrufen.

Dieses Objekt der Klasse CC; Aufruf der Funktion cc.Abstr(); Aufruf der Funktion cc.fun().

.

.


an der Methode void fun ( void ) interessiert:

- warum gibt es keinen virtuellen Spezifizierer?

- Wenn wir virtuell hinzufügen, was wird sich dann später ändern?


warum und wofür, hier ist der Code:

class base
{
public:
   virtual void HighPriorityTask() {}
   virtual void Task() {}
};
//+------------------------------------------------------------------+
class A: public base
{
public:
   virtual void HighPriorityTask() { Print(__FUNCSIG__); }
};
//+------------------------------------------------------------------+
class B: public base
{
public:
   virtual void Task() { Print(__FUNCSIG__); }
};

//+------------------------------------------------------------------+
void OnStart()
{
   base *obj[4];;
   obj[0] = new A; obj[1] = new A;  
   obj[2] = new B; obj[3] = new B; 
   for(int i=ArraySize(obj)-1; i>=0; i--)
   {
      obj[i].HighPriorityTask();
      obj[i].Task();
   }
   
   for(int i=ArraySize(obj)-1; i>=0; i--)
      delete obj[i];

2020.05.28 14:41:20.294 tst (EURUSD,H1) void B::Task()

2020.05.28 14:41:20.298 tst (EURUSD,H1) void B::Task()

2020.05.28 14:41:20.298 tst (EURUSD,H1) void A::HighPriorityTask()

2020.05.28 14:41:20.298 tst (EURUSD,H1) void A::HighPriorityTask()

es funktioniert so, wie ich es möchte - ich habe eine Basisklasse und erbe von ihr. Aber meine Nachkommen benötigen nur eine Methode, und ich möchte Objekte aufrufen, die zuerst die Methode HighPriorityTask() und dann Task() haben, unabhängig von der Reihenfolge der Deklaration und Initialisierung


alles in einer Schleife

Ist es möglich, dies auf einfache Art und Weise zu tun?

 
Igor Makanu:

und natürlich alles in einem Zyklus.

ist das mit einfachen Mitteln möglich?

Und warum zum Teufel sollte das in einem einzigen Zyklus geschehen?

Und warum ist sie auch natürlich?

Natürlich wird es mindestens zwei Zyklen geben.

 
Koldun Zloy:

Und warum zum Teufel sollte das im selben Zyklus geschehen?

Und warum ist sie auch natürlich?

Natürlich wird es mindestens zwei Zyklen geben.

OK, zwei Zyklen sind zwei Zyklen, also kein Wunder ((

 
Igor Makanu:

OK, 2 Zyklen sind 2 Zyklen, also kein Wunder ((

Sie könnten versuchen, die Schleifen ganz abzuschaffen.
Es gibt Beispiele dafür, wie man von 1 bis 100 ohne Schleifen und ohne Rekursion drucken kann.
Vielleicht helfen diese Beispiele, wenn es überhaupt relevant ist ))

Печать от 1 до 100 на C ++, без цикла и рекурсии | Портал информатики для гиков
  • 2020.01.01
  • espressocode.top
Ниже приводится программа на C ++, которая печатает от 1 до 100 без цикла и без рекурсии. #include using namespace std;    template
 
Roman:
Was ist der Sinn dieses Unsinns?
 
Igor Makanu:

Hier ist eine weitere Frage, hier ist derWiki-Artikel Abstract Class

Ich bin an einem C++-Beispiel interessiert

Das Ergebnis des Programms:

Programm:

Dieses Objekt der Klasse CB; Funktion cb.Abstr() aufrufen; Funktion cb.fun() aufrufen.

Dieses Objekt der Klasse CC; Aufruf der Funktion cc.Abstr(); Aufruf der Funktion cc.fun().

.

.


an der Methode void fun ( void ) interessiert:

- warum gibt es keinen virtuellen Spezifizierer?

- Wenn wir virtuell hinzufügen, was wird sich dann später ändern?


warum und wofür, hier ist der Code:

2020.05.28 14:41:20.294 tst (EURUSD,H1) void B::Task()

2020.05.28 14:41:20.298 tst (EURUSD,H1) void B::Task()

2020.05.28 14:41:20.298 tst (EURUSD,H1) void A::HighPriorityTask()

2020.05.28 14:41:20.298 tst (EURUSD,H1) void A::HighPriorityTask()

es funktioniert so, wie ich es möchte - ich habe eine Basisklasse und erbe von ihr. Aber meine Nachkommen benötigen nur eine Methode, und ich möchte Objekte aufrufen, die zuerst die Methode HighPriorityTask() und dann Task() haben, unabhängig von der Reihenfolge der Deklaration und Initialisierung


alles in einer Schleife

Ist dies mit einer einfachen Methode möglich?

1. Wenn Sie einen Zeiger der Basisklasse deklarieren und ein Kindobjekt erstellen, können Sie beim Aufruf von Methoden über denselben Zeiger der Basisklasse:

a) virtuelle Methoden werden von der Kindklasse aufgerufen (über die eigens zu diesem Zweck erstellte virtuelle Funktionstabelle)

b) Nicht-virtuelle Methoden werden von der Basisklasse aufgerufen. Selbst wenn sie in der untergeordneten Klasse außer Kraft gesetzt werden.

2. Wenn Sie eine einzelne Schleife haben wollen, dann

a) Sortieren Sie das Objekt-Array nach Typ.

b) Bewahren Sie für jede spezifische Aufgabe ein separates Array mit Zeigern auf Objekte auf, die diese Aufgaben lösen. D.h. alle Objekte, dieHighPriorityTask aufrufen müssen

sollte in einem separaten Array gespeichert werden, das zuerst aufgerufen werden sollte.

h.e. Wie können Sie sich vorstellen, dass im Allgemeinen ohne Sortierung die Hälfte aller Objekte zuerst ausgeführt wird und dann der Rest? :) Nun, wenn auch nur, um eine Warteschlange zu starten.

Aber das ist eine kreative Frage, man kann sich viele raffinierte Wege einfallen lassen, um ein Penny-Problem zu lösen))) Die Hauptsache ist, dass man nicht gegen die Gesetze der Physik verstößt und alles wird gut)))

 
Aleksey Mavrin:

2. Wenn Sie die gleiche Schleife verwenden wollen, dann

a) Sortiere das Array der Objekte nach Typ.

b) Halten Sie für bestimmte Aufgaben eine separate Reihe von Zeigern auf Objekte bereit, die diese Aufgaben erfüllen. D.h. alle Objekte, dieHighPriorityTask aufrufen müssen

sollte in einem separaten Array gespeichert werden, das zuerst aufgerufen werden sollte.

h.e. Wie können Sie sich vorstellen, dass im Allgemeinen ohne Sortierung die Hälfte der Objekte zuerst ausgeführt wird und dann der Rest? :) Nun, wenn auch nur, um eine Warteschlange zu starten.

Aber das ist eine kreative Frage, man kann sich viele raffinierte Wege einfallen lassen, um eine Pfennigaufgabe zu lösen))) Die Hauptsache ist, dass man nicht gegen die Gesetze der Physik verstößt, und alles wird gut)))

Ich will das nicht, ich glaube, der Compiler wird die leeren Methoden optimieren.

Aleksey Mavrin:

1. Wenn Sie einen Zeiger einer Basisklasse deklarieren und ein Kindobjekt erzeugen, dann wird beim Aufruf von Methoden über eben diesen Zeiger der Basisklasse

a) virtuelle Methoden werden von der Kindklasse aufgerufen (über die eigens zu diesem Zweck erstellte virtuelle Funktionstabelle)

b) Nicht-virtuelle Methoden werden von der Basisklasse aufgerufen. Selbst wenn sie in der untergeordneten Klasse außer Kraft gesetzt werden.

Ja, ich erinnere mich nicht, dass ich gerade die json-Bibliothekhttps://www.mql5.com/en/code/11134(ich fand es auf einem githab irgendwo ein bisschen frischer als die KB) behoben.

und es gab Compiler-Warnungen

veraltetes Verhalten, versteckter Methodenaufruf wird in einer zukünftigen MQL-Compilerversion deaktiviert werden

durch Angabe einer Methode in einer Klasse festgelegt

this.JSONValue:: getLong(getValue(index),out);

Danke, das ist ein ziemlich klares Bild

 
Igor Makanu:

definitiv nicht wollen, denke ich, dass der Compiler leere Methoden optimieren wird

Aber der Aufruf einer leeren Funktion wird wahrscheinlich sowieso nicht viel bringen.

Igor Makanu:

OK, 2 Schleifen bedeutet 2 Schleifen, also wird es kein Wunder geben ((

Warum sollte ich etwas in eine Schleife packen, was logischerweise in zwei Schleifen erledigt wird? Weil es keinen Geschwindigkeits-, Klarheits- und Vereinfachungsgewinn gibt und die Größe von Festplatten längst in Megabytes statt in Megabytes gemessen wird.

 
Andrei Trukhanovich:

Warum sollte man das, was logischerweise in zwei Zyklen erledigt werden kann, in einen einzigen Zyklus packen? Weil es keinen Gewinn an Geschwindigkeit, Klarheit oder Einfachheit gibt und die Größe von Festplatten nicht in Megabytes gemessen wird.

Ich habe sie noch nicht einmal benutzt! ))))

Sie müssen nur die Spezifikationen kennen, um etwas Ähnliches wie normale Methodenaufrufe zu machen.

Vielen Dank, das erklärt es sehr gut.

Andrei Trukhanovich:

Virtuell? Nicht unbedingt.

Ich wünschte, ich könnte Ihnen ein Beispiel zeigen, die Frage stellte sich wegen der großen Auswahl an Polymorphismus bedeutet, entweder virtuell oder ohne sie, oder erben oder schließen Sie diese Methode in abgeleiteten Klassen

 
Roman:

Sie können versuchen, die Schleifen ganz abzuschaffen.
Es gibt Beispiele dafür, wie man von 1 bis 100 ohne Schleifen und ohne Rekursion drucken kann.
Vielleicht helfen diese Beispiele, wenn es überhaupt relevant ist ))

Und warum? Ein anderes Muster. Das Einzige, was die Adepten des Musters nicht erkannt haben, ist, dass es offensichtlich nicht orthodox und kanonisch ist. Warum nicht Rekursion? Auch Rekursion, nur nicht entlang, sondern quer.