Auteur Sujet: Tableau d'objet  (Lu 21842 fois)

jac.fil

  • Newbie
  • *
  • Messages: 15
    • Voir le profil
Re : Tableau d'objet
« Réponse #15 le: juillet 14, 2018, 08:36:22 am »
Je ne pensais pas que ma modeste contribution allait déclencher autant de réponses

Je vais les lire tranquillement et essayer de comprendre, mais vous êtes tous partis dans des sphères qui dépassent très largement mes modestes connaissances en C++......

Je remercie tous les contributeurs qui ont pris le temps de répondre.

Je sais que mon code n'est pas très pur, mais pour l'instant la gestion de mes cantons fonctionne parfaitement et rempli parfaitement son office. 3 convois se suivent sans aucun problème sur mon réseau.

Ceci étant, il faut constamment essayer de se former et s'améliorer  :) :)

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Tableau d'objet
« Réponse #16 le: juillet 14, 2018, 09:50:46 am »
Une dernière solution qui évite de cosommer plus de mémoire que nécessaire mais qui n'est applicable que pour un tableau alloué statiquement est de référencer directement le constructeur dans l'initialisation du tableau. Ceci infirme une de mes affirmation précédentes. Je pense que cette façon de faire n'est apparue qu'avec C++11.

Comme ceci :

class Led {
  private: uint8_t mPin;
  public: Led(uint8_t inPin) : mPin(inPin) {}
  public: void display() { Serial.println(mPin); }
};

Led ledTab[] = {
  Led(10),
  Led(8),
  Led(3),
  Led(2)
};


void setup()
{
  Serial.begin(115200);
  for (int i = 0; i < 4; i++) {
    ledTab[i].display();
  }
}

void loop()
{
}
« Modifié: juillet 14, 2018, 09:53:01 am par Jean-Luc »
Cordialement

Pierre59

  • Sr. Member
  • ****
  • Messages: 324
    • Voir le profil
Re : Tableau d'objet
« Réponse #17 le: juillet 15, 2018, 10:09:14 am »
Bonjour

Le programme précédent avec 4 leds fonctionne très bien tel quel, mais si on veut le faire évoluer les choses vont se compliquer. Voici deux exemples entre autres qui vont poser problème :

Premier cas

Supposons que je veuille faire quelques traitements sur une led, par exemple la deuxième, comme on le recommande je vais utiliser une variable intermédiaire pour économiser des indiçages superflus, donc écrire quelque chose comme cela :

Led led=ledTab[1];

On a fait une copie sans trop s'en rendre compte, c'est "foutu" les leds du tableau ne seront pas modifiées si on modifie la copie.

Deuxième cas

Le programme précédent ayant l'air de fonctionner (et il fonctionne), en tant que "débutant" je m'enhardi en essayant de faire de l'héritage, de façon classique et comme dans les articles sur les objets de Locoduino, j'essaye de faire une LedBicouleur héritant de Led. Cela donne quelque chose comme cela :

class Led {
  protected: int mPin;
  public: Led(int inPin) : mPin(inPin) {}
  public: void display() { printf("%d ",mPin); }
};

class LedBicouleur : public Led {
  private: int mPin2; // deuxieme pin
  public: LedBicouleur(int inPin,int inPin2) : Led(inPin),mPin2(inPin2) {}
  public: void display() { printf("%d-%d ",mPin,mPin2);  }
};

Led ledTab[] = {
  Led(10),
  LedBicouleur(8,9),
  Led(3),
  Led(2)
};

int main(int argc, char **argv) {
  for (int i = 0; i < 4; i++) {
    ledTab[i].display();
   }
}

Comme je tiens à pouvoir facilement exécuter les programmes, c'est écrit en C++ standard (pas spécialement pour l'Arduino), donc il me faut adapter les entrées/sorties et avoir une fonction main à la place du setup(), en plus j'ai changé les uint8_t en int (pour la lisibilité). J'ai du passer aussi la variable mPin de Led de private à protected (pour l'héritage).

La classe LedBicouleur hérite de la classe Led, elle rajoute une variable pour la deuxième pin, un constructeur comme il faut et une nouvelle méthode display() pour afficher les deux pins.

Dans le tableau de leds j'ai changé une Led en LedBicouleur. On exécute, cela donne :

10 8 3 2

Grosse déception, les deux pins de la LedBicouleur ne sont pas affichées  :(

En tant qu'informaticien le tableau de leds me pose un problème une LedBicouleur prend plus de place qu'une Led (un entier de plus), le compilateur n'a que deux possibilités, soit il tronque la LedBicouleur à la taille de Led, soit il alloue de la place pour 4 LedBicouleur. Après vérifications (sizeof) il me semble que le compilateur tronque.

Bilan

La BONNE solution pour éviter ces problèmes (et d'autres) c'est d'utiliser systématiquement des pointeurs sur les objets quand on veut les manipuler. Voila ce que cela donne :

class Led {
  protected: int mPin; float x;
  public: Led(int inPin) : mPin(inPin) {}
  public: virtual void display() { printf("%d ",mPin); }
};

class LedBicouleur : public Led {
  private: int mPin2; double x,y,z; // deuxieme pin
  public: LedBicouleur(int inPin,int inPin2) : Led(inPin),mPin2(inPin2) {}
  public: virtual void display() { printf("%d-%d ",mPin,mPin2);  }
};

Led* ledTab[] = {
  new Led(10),
  new LedBicouleur(8,9),
  new Led(3),
  new Led(2)
};

int main(int argc, char **argv) {
  for (int i = 0; i < 4; i++) {
    ledTab[i]->display();
   }
}

Cela affiche :

10 8-9 3 2

Les deux objets n'ont pas été modifiés (à part l'ajout de "virtual" à la méthode display() (nécessaires pour le polymorphisme)
Le tableau de Leds à été transformé en tableau de pointeurs de Leds, et le programme de test (main()) à été modifié en conséquence.

Amicalement

Pierre

jac.fil

  • Newbie
  • *
  • Messages: 15
    • Voir le profil
Re : Tableau d'objet
« Réponse #18 le: juillet 16, 2018, 01:21:15 pm »
Initiateur néophyte de cette discussion , j'ai lu attentivement tous vos posts.

Je suis bien persuadé à présent grâce à vous tous qu'il faut passer par des pointeurs pour les tableaux et j'ai par ailleurs bien étudié les pointeurs et leur rôle me semble moins obscur à défaut de les maîtriser complètement (lourde tâche !!!)

Certain d'entre vous utilise Led* avant de déclarer le tableau , quel est la signification ??

Merci d'avance pour votre retour.

PS : au fait en réponse à bodyAndCo

Pas bien cherché, il y a tout sur locoduino.org,

Ces tableaux qui peuvent nous simplifier le développement Arduino : http://www.locoduino.org/spip.phparticle227
J'avais bien lu cet article, mais celui ci n'aborde pas les objets d'où ma question et étant donné les discussions qu'elle a fait naître on est vraiment très loin de celui-ci ,  fort bien fait par ailleurs pour expliquer l'utilisation classique des tableaux avec les variables habituelles du C


Pierre59

  • Sr. Member
  • ****
  • Messages: 324
    • Voir le profil
Re : Tableau d'objet
« Réponse #19 le: juillet 16, 2018, 01:55:19 pm »

Bonjour

Faut pas trop se polariser sur les pointeurs, certes c'est à la base de pas mal de choses en C et C++ (par exemple les tableaux, quand on écrit t[j] le compilateur voir cela comme *(t+j)  donc des pointeurs), mais bien qu'ayant enseigné le C et le C++ pendant de nombreuses années, j'utilise au minimum les pointeurs pour des problèmes de lisibilité des programmes.

L'utilisation de pointeurs sur les objets, c'est plutôt simple :

- pour la déclaration on met une étoile derrière le type, par exemple Led devient Led* (Led c'est un objet, Led* c'est un pointeur sur un objet)

- pour l'utilisation des objets au lieu de mettre objet.variable ou objet.fonction() on met objet->variable ou objet->fonction(), c'est à peu près tout (et on peut quasiment oublier les pointeurs).

Pierre

jac.fil

  • Newbie
  • *
  • Messages: 15
    • Voir le profil
Re : Tableau d'objet
« Réponse #20 le: juillet 16, 2018, 04:03:10 pm »
Merci Marc-Henry pour le retour aussi rapidement et surtout pour les explications.

Du coup cela conforte mon idée sur les modifications à apporter à mon programme, et surtout si cela fonctionne, ca ne bouleverse pas toute sa structure.

Je vais essayer cela mais après 2 mois  d'électronique et de programmation, je me change un peu les idées en faisant du décor, c'est quand même du modélisme ferroviaire la base de notre hobby  ;) ;)


Très cordialement

jac.fil

  • Newbie
  • *
  • Messages: 15
    • Voir le profil
Re : Tableau d'objet
« Réponse #21 le: juillet 16, 2018, 07:08:17 pm »
Rendons à César ......
Merci Pierre et non pas Marc Henry pour la réponse d' aujourd'hui , désolé de mon erreur, ces pointeurs me perturbent  ;D ;D ;D ;D