[RESOLU] Valeur membre de classe dans un tableau d'objet via autre objet KO

Bonjour,
J’ai le soucis de développement C++ suivant : depuis mon programme principal j’ai un objet (nommons le Objet) qui contient un tableau d’Objet2. Lorsque depuis une méthode d’Objet j’essaye de récuperer la valeur d’un membre (public) d’Objet2, la valeur retournée ne correspond pas à l’attendu… D’aprés les données je pense récuperer une adresse et non la valeur de cette adresse. (valeur consécutives pour 2 instance d’Objet2).
J’ai repotassé tout ce que j’ai pu à propos des tableaux / pointeurs, fait qques essais mais sans réussite.

Si un pro du C++ passe dans le coin pour m’aiguiller ça serait avec plaisir.

Ci dessous et en PJ le code mini pour représenter le pb. Je ne sais si c’est important mais je suis sur un ESP8266 et pas un arduino. Compil avec IDE Arduino 1.8.12
testObjet.ino

#include "objet.h"

monObjet objA('A');
monObjet objB('B');
monObjet objC('C');

void setup() {
  Serial.begin(115200);
  objA.begin (&Serial);
  objB.begin (&Serial);
}

void loop() {
  Serial.println("/////////////");
  objA.print();
  Serial.println("/////////////");
  delay(2000);
  Serial.println("/////////////");
  objB.print();
  Serial.println("/////////////");
  delay(2000);
}

Objet.h

#ifndef __OBJET_H
#define __OBJET_H
#include "Arduino.h";
#include "objet2.h";

class monObjet {
  public:
    monObjet(char name);
    void begin(HardwareSerial *serial);
    void print();
    Objet2 _secondTab[];
  private:
    char _nom;
    HardwareSerial *_stream;
};
#endif

Objet.cpp

#include "objet.h"

Objet2 obj21(21);
Objet2 obj22(22);
Objet2 obj23(23);


monObjet::monObjet(char nom) {
  _nom = nom;
  Objet2 _secondTab[] = {obj21, obj22, obj23};
}

void monObjet::begin(HardwareSerial *serial) {
  _stream = serial;
  _stream->println("""""""""""");
  _stream->println(obj21._myVar); // <- Affiche valeur attendue (21)
  _stream->println("""""""""""");
  _stream->println("""""""""""");
  _stream->println(obj22._myVar); // <- Affiche valeur attendue (22)
  _stream->println("""""""""""");
  _stream->println("----------");
  _stream->println(_secondTab[0]._myVar); // <- Affiche 65, 66 en fonction de l'instance. Je souhaite voir 21,22..
  _stream->println("----------");
}

void monObjet::print() {
  _stream->println("//Object:");
  _stream->println(_nom);
  _stream->println("+++++++++");
  _stream->println(obj21._myVar);// <- Affiche valeur attendue (21)
  _stream->println("+++++++++");
  for (int i = 0; i < 3; i++) {
    _stream->println("#############");
    _stream->println(_secondTab[i]._myVar);// <- Affiche 65,0,0 ; 66,0,0  en fonction de l'instance
    _stream->println("#############");
  }
}

Objet2.h

#ifndef __OBJET2_H
#define __OBJET2_H
#include "Arduino.h";

class Objet2 {
  public:
    Objet2(int x);
    byte _myVar;
};
#endif

Objet2.cpp

#include "objet2.h"

Objet2::Objet2(int x) {
  _myVar = x;
}

résultat

21


22

----------
65
----------

21


22

----------
66
----------
/////////////
//Object:
A
+++++++++
21
+++++++++
#############
65
#############
#############
0
#############
#############
0
#############
/////////////
/////////////
//Object:
B
+++++++++
21
+++++++++
#############
66
#############
#############
0
#############
#############
0
#############

Au lieu de 65,0,0 j’attend 21,22,23

testObject.zip (1.77 KB)

Bonjour,

Ici

monObjet::monObjet(char nom) {
  _nom = nom;
  Objet2 _secondTab[] = {obj21, obj22, obj23};
}

tu redéfinis en local un second objet _secondTab au lieu d'affecter l'objet _secondTab de la class monObjet.

Tu aurais du faire

monObjet::monObjet(char nom) {
  _nom = nom;
  _secondTab[0] = obj21;
  _secondTab[1] = obj22;
  _secondTab[2] = obj23;
}

et bien sur dimensionner la table dans la class nonObjet
Objet2 _secondTab[3];
mais il faudrait que Objet2 ait un constructeur sans argument.

class monObjet {
  ...
    
    Objet2 _secondTab[];
 
 ...
};

La taille du tableau _secondTab n'est pas définie. Losque l'objet est consruit, il ne peut s'allouer un tableau d'objets, puisqu'il ne sait pas combien on en veut.
La seule possibilité pour le compilateur est de comprendre ceci :

class monObjet {
  ...
    
    Objet2 * _secondTab;
 
 ...
};

Le membre _secondTab n'est pas un tableau, mais un bête pointeur (à initialiser donc).

Pour cela, dans le constructeur, tu fais :

 _secondTab = new Objet2[3];

avec le delete correspondant dans le destructeur de Objet.

Ou bien tu fais comme a dit lesept.

Merci pour ces réponses. Je vais essayer de graver dans ma tête ce besoin d'initiation des tableaux.
Je vais mettre en œuvre ce soir mais je ne doute pas que ça se déroule bien mieux :wink:

Hmmm la y’a vraiment un truc.
Dieux sais que les explication me semblaient claires et explicites.
J’ai fait comme préconisé par Kamill (enfin il me semble)
Objet.h

class monObjet {
  public:
    monObjet(char name);
    void begin(HardwareSerial *serial);
    void print();
    Objet2 _secondTab[3];
  private:
    char _nom;
    HardwareSerial *_stream;
};

Objet.cpp

#include "objet.h"
Objet2 obj21(21);
Objet2 obj22(22);
Objet2 obj23(23);

monObjet::monObjet(char nom) {
  _nom = nom;
  _secondTab[0] = obj21;
  _secondTab[1] = obj22;
  _secondTab[2] = obj23;
}

void monObjet::begin(HardwareSerial *serial) {
  _stream = serial;
  _stream->println("-----DIRECT IDX-----");
  _stream->println(_secondTab[0]._myVar);// <- Affiche 0
  _stream->println(_secondTab[1]._myVar);// <- Affiche 0
  _stream->println(_secondTab[2]._myVar);//<- Affiche 0
  _stream->println("-----DIRECT IDX-----");
  for (int i = 0; i < 3; i++) {
    _stream->println("-----+-----");
    _stream->println(_secondTab[i]._myVar);// <- Affiche 0,0,0 
    _stream->println("-----+-----");
  }
}

void monObjet::print() {
  _stream->println("//Object:");
  _stream->println(_nom);
  for (int i = 0; i < 3; i++) {
    _stream->println("#############");
      _stream->println(_secondTab[i]._myVar);// <- Affiche 0,0,0 
    _stream->println("#############");
  }
}

Bref je suis :confused: :confused: :confused: .
Qu’ai je encore fait de mal !!!
Merci

Tu as un constructeur sans paramètres pour Objet2 ?
Si non, il en faut en créer un.

tu ne donnes pas le message d'erreur...

je plussoie la réponse de kamill.

Quand tu crées un Objet, le compilateur met en place le code pour créer 3 Objet2.
Donc 3 appels au constructeur de Objet2 ... sans passer aucun argument (que pourrait-il passer) ?
Le compilateur ne peut pas utiliser le ctor de Objet2 qui attend un argument.
Il lui faut absolument un ctor sans argument.
L'objet ainsi créé peut être inutilisable, ce n'est pas grave car plus tard tu remplaces ces 3 Objet2 par des instances correctement initialisées.

Bonjour,

oui un constructeur sans arg est défini pour Objet2
Objet2.h

class Objet2 {
  public:
    Objet2();
}

Objet2.cpp

Objet2::Objet2() {
}

et le résultat n’est pas un ou des messages d’erreur, mais la valeur 0 affichée tout le temps (au lieu de l’attendu 21,22). Le code complet en zip au cas ou
Merci.

testObject.zip (1.77 KB)

Le problème est que tu crées les objets statiquement.
L’objet statique objA est initialisé dans son constructeur avec les objets obj21 obj22 obj23, or rien ne garanti que ces oblets soient créés avant objA.
L’affectation dans le constructeur de monObjet peut se faire avant que les Objet2 ne soient crées.

Une des solution est de faire une méthode init() dans la class monObjet pour pouvoir initialiser explicitement les objets.
Une autre solution est de créer les objA objB dynamiquement.
Une autre solution est, au lieu d’inclure des Objet2, c’est d’inclure des pointeurs sur Objet2.

Ca y est !!
Effectivement j’ai mis l’affectation dans la méthode begin - j’en ai de toute façon besoin dans le code envisagé; et la les valeurs sont correctes :smiley:

Je me lancerai bien dans l’allocation dynamique, mais pas sur de bien gérer la suprression, pour le moment je reste sur cette solution et continu sur le projet (un peu plus interessant que monObjet et Objet2…)
Hâte de ‘partager’ le résultat dans la section ‘Projet Fini’

Pour référence le code final en PJ.
Merci à vous deux pour l’aide.

testObject.zip (1.73 KB)