Questions sur la POO dans MQL5 - page 67

 

Voici une autre question, voici l'article deWiki Classe abstraite

Je suis intéressé par un exemple en C++

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

Le résultat du programme :

Programme :

Cet objet de la classe CB ; appeler la fonction cb.Abstr() ; appeler la fonction cb.fun().

Cet objet de la classe CC ; appeler la fonction cc.Abstr() ; appeler la fonction cc.fun().

.

.


intéressé par la méthode void fun ( void ) :

- pourquoi n'y a-t-il pas de spécificateur virtuel ?

- si nous ajoutons du virtuel, qu'est-ce que cela changera par la suite ?


pourquoi et pour quoi faire, voici le 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()

Mais mes descendants n'auront besoin que d'une seule méthode et je veux appeler les objets qui ont la méthode HighPriorityTask() en premier et ensuite Task() indépendamment de la séquence de déclaration et d'initialisation.


tout en une seule boucle

est-il possible de faire cela de manière simple ?

 
Igor Makanu:

et bien sûr, tout cela en un seul cycle.

est-ce possible par des moyens simples ?

Et pourquoi diable faudrait-il le faire en un seul cycle ?

Et pourquoi est-ce aussi naturel ?

Naturellement, il y aura au moins deux cycles.

 
Koldun Zloy:

Et pourquoi diable cela devrait-il être fait dans le même cycle ?

Et pourquoi est-ce aussi naturel ?

Naturellement, il y aura au moins deux cycles.

OK, deux cycles signifie deux cycles, donc pas de miracle ((

 
Igor Makanu:

OK, 2 cycles signifie 2 cycles, donc pas de miracle ((

Vous pourriez essayer de vous débarrasser complètement des boucles.
Il existe des exemples permettant d'imprimer de 1 à 100 sans boucle et sans récursion.
Peut-être que ces exemples vous aideront, si tant est que ce soit pertinent ;))

Печать от 1 до 100 на C ++, без цикла и рекурсии | Портал информатики для гиков
  • 2020.01.01
  • espressocode.top
Ниже приводится программа на C ++, которая печатает от 1 до 100 без цикла и без рекурсии. #include using namespace std;    template
 
Roman:
Quel est le but de cette absurdité ?
 
Igor Makanu:

Voici une autre question, voici l'article deWiki Classe abstraite

Je suis intéressé par un exemple en C++

Le résultat du programme :

Programme :

Cet objet de la classe CB ; appeler la fonction cb.Abstr() ; appeler la fonction cb.fun().

Cet objet de la classe CC ; appeler la fonction cc.Abstr() ; appeler la fonction cc.fun().

.

.


intéressé par la méthode void fun ( void ) :

- pourquoi n'y a-t-il pas de spécificateur virtuel ?

- si nous ajoutons du virtuel, qu'est-ce que cela changera par la suite ?


pourquoi et pour quoi faire, voici le 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()

Mais mes descendants n'auront besoin que d'une seule méthode et je veux appeler les objets qui ont la méthode HighPriorityTask() en premier et ensuite Task() indépendamment de la séquence de déclaration et d'initialisation.


tout en une seule boucle

est-il possible de faire cela de manière simple ?

1. Si vous déclarez un pointeur de classe de base et créez un objet enfant, alors lors de l'appel de méthodes via ce même pointeur de la classe de base :

a) les méthodes virtuelles sont appelées par la classe enfant (via le tableau des fonctions virtuelles spécialement créé à cet effet)

b) les méthodes non virtuelles sont appelées par la classe de base. Même si elles sont surchargées dans la classe enfant.

2. Si vous voulez avoir une seule boucle, alors

a) Triez le tableau d'objets par type.

b) Pour chaque tâche spécifique, gardez un tableau séparé de pointeurs vers les objets qui résolvent ces tâches. C'est-à-dire tous les objets qui doivent appelerHighPriorityTask

doit être stocké dans un tableau séparé, qui doit être appelé en premier.

c.-à-d., comment pouvez-vous imaginer théoriquement - sans trier - que dans un passage de la boucle, la première moitié des objets sera exécutée, et ensuite le reste ? :) Eh bien, si seulement pour commencer une file d'attente de travail.

Mais il s'agit d'une question créative, on peut trouver beaucoup de moyens sophistiqués pour résoudre un problème de sous))) L'essentiel est de ne pas empiéter sur les lois de la physique et tout ira bien))).

 
Aleksey Mavrin:

2. Si vous voulez utiliser la même boucle, alors

a) Triez le tableau d'objets par type.

b) Pour des tâches spécifiques, gardez un tableau séparé de pointeurs vers les objets qui exécutent ces tâches. C'est-à-dire tous les objets qui doivent appelerHighPriorityTask

doit être stocké dans un tableau séparé, qui doit être appelé en premier.

h.e. Comment pouvez-vous imaginer qu'en général, sans tri, la moitié des objets seront exécutés en premier, et ensuite le reste ? :) Eh bien, si seulement pour commencer une file d'attente de travail.

Mais il s'agit d'une question créative, vous pouvez imaginer un tas de moyens sophistiqués pour résoudre une tâche simple))) L'essentiel est de ne pas empiéter sur les lois de la physique, et tout ira bien))).

Je ne veux pas le faire, je crois que le compilateur optimisera les méthodes vides.

Aleksey Mavrin:

1. Si vous déclarez un pointeur d'une classe de base et créez un objet enfant, alors lorsque vous appelez des méthodes via ce même pointeur de la classe de base

a) les méthodes virtuelles sont appelées par la classe enfant (via le tableau des fonctions virtuelles spécialement créé à cet effet)

b) les méthodes non virtuelles sont appelées par la classe de base. Même si elles sont surchargées dans la classe enfant.

oui, je ne me souviens pas que je viens de corriger la bibliothèque jsonhttps://www.mql5.com/en/code/11134(je l'ai trouvé sur un githab quelque part un peu plus frais que la KB).

et il y avait des avertissements du compilateur

comportement déprécié, l'appel de méthode caché sera désactivé dans une future version du compilateur MQL.

peut être corrigée en spécifiant une méthode dans une classe

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

Merci, c'est une image assez claire

 
Igor Makanu:

ne veulent absolument pas, je pense que le compilateur va optimiser les méthodes vides

Mais l'appel d'une fonction vide ne risque pas de manger grand-chose de toute façon.

Igor Makanu:

OK, 2 boucles signifie 2 boucles, donc il n'y aura pas de miracle ((

Pourquoi devrais-je faire passer dans une seule boucle quelque chose qui se fait logiquement en deux boucles ? Parce qu'il n'y a aucun gain de vitesse, de clarté et de simplicité et que la taille des disques durs se mesure en mégaoctets au lieu de mégaoctets depuis longtemps.

 
Andrei Trukhanovich:

Pourquoi condenser en un seul cycle ce qui peut logiquement être fait en deux ? Parce qu'il n'y a pas de gain de vitesse, de clarté ou de simplicité, et que la taille des disques durs ne se mesure pas en mégaoctets.

Je ne les ai même pas encore utilisés ! ))))

il suffit de connaître les spécifications pour faire quelque chose de similaire aux appels de méthode normaux

Merci. Cela explique très bien les choses.

Andrei Trukhanovich:

Virtuel ? Pas nécessairement.

J'aimerais pouvoir vous montrer un exemple, la question s'est posée à cause du grand choix de moyens de polymorphisme, soit virtuel ou sans, soit hériter ou fermer cette méthode dans les classes dérivées

 
Roman:

Vous pouvez essayer de vous débarrasser complètement des boucles.
Il existe des exemples permettant d'imprimer de 1 à 100 sans boucle et sans récursion.
Peut-être que ces exemples vous aideront, si c'est même pertinent ;))

Pourquoi ? Un autre modèle. La seule chose que les adeptes du pattern n'ont pas reconnu, c'est qu'il n'est évidemment pas orthodoxe et canonique. Pourquoi pas la récursion ? C'est aussi une récursion, mais pas le long, mais à travers.