Go Down

Topic: Objet d'une classe en paramètre dans une autre classe (Read 345 times) previous topic - next topic

Geeks

Bonjour à la communauté.

Je cherche, depuis plusieurs jours à faire passer en paramètre un objet d'une classe vers une autre classe.

Un exemple que je cherche à faire :

main.ino
Code: [Select]

#include <LiquidCrystal.h>
#include "menuLCD.h"

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
MenuLCD menu(lcd); //Ici, je cherche à faire passer en paramètre l'objet lcd de façon à pouvoir utiliser lcd.clear()...

void setup () {
  Serial.begin(9600);
  Serial.flush();

  lcd.begin(16, 2);
}

void loop() {
 menu.start(1); //Ici, j'utiliserais des objets de la classe MenuLCD
 lcd.println("Hello world"); //Ici, j'utilise lcd comme d'habitude
}


menuLCD.h
Code: [Select]

#ifndef menuLCD_h
#define menuLCD_h

class MenuLCD
{
  public :
    MenuLCD(void);  //Constructor //Ici, je ne sais pas comment déclarer pour recevoir l'objet lcd
    start(int level);
  private :
};

#endif


menuLCD.cpp
Code: [Select]

#include "menuLCD.h"

MenuLCD::MenuLCD(void) //ici, comment reprendre la déclaration de lcd
{
    lcd.clear(); //Ici, on peut utiliser l'objet transmis  
}

MenuLCD::start(int level)
{
   lcd.clear();
   lcd.setCursor(0,0); //Colonne, Ligne
   lcd.print("menu");
   lcd.println(level);
}


De ce que j'ai lu, sans savoir comment le faire, il faut passer par des pointeurs, ors il existe soit "*" soit "&". Enfin, comment l'intégrer ?

kamill

Bonjour,

Il faut que tu crées un constructeur qui prenne comme paramètre une référence vers ton instance lcd.

Geeks

On est bien d'accord avec ça !

Mais quelle type de paramètre ? C'est pas un integer, c'est pas un String...

En gros:
Code: [Select]

public :
    MenuLCD(type *lcd);  //Constructor //Ici, je ne sais pas comment déclarer pour recevoir l'objet lcd
    //ou
    MenuLCD(type &lcd);  //Constructor //Ici, je ne sais pas comment déclarer pour recevoir l'objet lcd

hbachetti

Tu peux passer par un passage de paramètre par référence et conserver la référence dans les membres privés de la classe :

Code: [Select]

#ifndef menuLCD_h
#define menuLCD_h

#include <LiquidCrystal.h>

class MenuLCD
{
  private:
    LiquidCrystal &myLcd;

  public :
    MenuLCD(LiquidCrystal &lcd);
    start(int level);
};

#endif


Code: [Select]

#include "menuLCD.h"

MenuLCD::MenuLCD(LiquidCrystal &lcd)
{
  myLcd = lcd;
  myLcd.clear();
}

MenuLCD::start(int level)
{
  myLcd.clear();
  myLcd.setCursor(0, 0); //Colonne, Ligne
  myLcd.print("menu");
  myLcd.println(level);
}


Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

hbachetti

L'appel à lcd.begin() est dans le setup.

Le LCD est utilisé dans le constructeur : myLcd.clear().

Chronologiquement ce n'est pas OK. Il vaudrait mieux ne pas appeler de méthode de lcd dans le constructeur.
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

Geeks

En effet, ça ne fonctionne pas... Mais, chronologiquement non plus  :smiley-confuse:

menuLCD.h
Code: [Select]

#ifndef menuLCD_h
#define menuLCD_h

#include "ExaNumericLcdMidasI2C.h"


class MenuLCD
{
  public :
    MenuLCD(LcdMidasI2c &lcd);  //Constructor
    getTest(void);
  private :
    LcdMidasI2c &_lcd;  //LCD MIDAS I2C Librarie ExaNumericLcdMidasI2C
};

#endif


menuLCD.cpp
Code: [Select]

#include "menuLCD.h"

MenuLCD::MenuLCD(LcdMidasI2c &lcd)
{
  _lcd = lcd;
}

MenuLCD::getTest(void)
{
  _lcd.clear();
  _lcd.setCursor(0,0); //Colonne, Ligne
  _lcd.print("Hello world");
}


main.ino
Code: [Select]

#include <LiquidCrystal.h>
#include "menuLCD.h"

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
MenuLCD menuUser(lcd); //Ici, je cherche à faire passer en paramètre l'objet lcd de façon à pouvoir utiliser

void setup () {
  Serial.begin(9600);
  Serial.flush();

  lcd.begin(16, 2);
}

void loop() {
 menuUser.getTest();
}


Sauf que rien ne s'affiche

hbachetti


Et hop on passe d'un LCD à un LCD I2C ...

LcdMidasI2c : connais pas. Quelle librairie ?

Tu as essayé d'afficher avec un sketch simple ?
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

kamill

Il faut que la class de l'instance que tu passes dans le constructeur soit la même (ou une class héritée) que celle déclarée dans le constructeur.
Dans le constructeur tu as une class LcdMidasI2c
Code: [Select]
   MenuLCD(LcdMidasI2c &lcd);  //Constructor
et tu lui passes un objet de class LiquidCrystal
Code: [Select]
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
MenuLCD menuUser(lcd); //Ici, je cherche à faire passer en paramètre l'objet lcd de façon à pouvoir utiliser


hbachetti

Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

Geeks

Je reprends :
Et hop on passe d'un LCD à un LCD I2C ...

LcdMidasI2c : connais pas. Quelle librairie ?

Tu as essayé d'afficher avec un sketch simple ?

C'est la même librarie que liquidSchristal, j'ai juste refais mes appels pour correspondre a celui que j'utilise. Mêmes fonctions, même nom, mêmes variables toussa.

Étonnant que cela puisse compiler non ?

En effet ! Je suis même surpris que ça fonctionne en partie...

Ce qui me fais pensé à:
1- est-ce que je pointe au bon endroit ?
2- est-ce que le contenu de mon pointeur à changé ?
3- comment vérifier que je passe bien l'instance créé dans le main, dans ma classe ?
4- existe-t-il une solution plus adhéquate ?

Bref, je suis dans le doute  :smiley-roll: 

hbachetti

Sans le code de ExaNumericLcdMidasI2C.h impossible de dire quoi que ce soit.
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

Geeks

Voilà donc le .h de la classe LCD.

https://framabin.org/p/?b9f84093ef50ebdd#+cOYopTYpeea4kTFxkCzhXst49oK8Fe8cvDJpdanA74=

Geeks

Et bien...
Ça fonctionne !

En fait, c'est un problème de pointeur. J'ai fini par me poser la question, est-ce que j'affecte le pointeur avec le bon endroit ? Et la réponse était pire, le pointeur n'étais tout simplement pas rempli. Rien à voir avec la classe exa... Bref !

Je met la solution au cas ou ça en intéresserais d'autres :
Donc, mon main, réduit pour les tests :

Code: [Select]

#include <LiquidCrystal.h>
#include "menuLCD.h"        //Le chemin de ma classe qui héritera de l'objet lcd

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
MenuLCD menuUser(lcd); //Ici, nous instancions la classe MenuLCD avec l'objet lcd passé en paramètre pointeur

void setup () {
  Serial.begin(9600);
  Serial.flush();

  lcd.begin(16, 2); //Utilisation de la classe LiquidChristal ou de exa.. Nombre de colonnes 16, nombre de ligne 2

  menuUser.getTest(); //ici, nous affichons le contenu de getTest() qui fera appel à l'objet passé en paramètre
}

void loop() {
 //Vide pour les essais !
}


Voyons, donc le .h de ma classe:
Code: [Select]

#ifndef menuLCD_h
#define menuLCD_h

#include <LiquidCrystal.h>  //La librairie parente pour laquelle nous cherchons à utiliser ses membres

class MenuLCD
{
  public :
    MenuLCD(LiquidCrystal &lcd);  //Constructeur avec passage en paramètre de l'objet au travers d'un pointeur
    void getTest(void);
   
  private :
    LiquidCrystal *_lcd;  //L'instanciation de la classe liquidCrystal avec comme paramètres, ceux de l'objet pointé
};


La différence était ici... dans la partie private ! mais pas que...

Voyons donc le .cpp
Code: [Select]

#include "menuLCD.h"

MenuLCD::MenuLCD(LiquidCrystal &lcd) //Passage en paramètre de l'objet
{
  _lcd = &lcd; //Nous remplissons le pointeur avec l'objet pointé
}

void MenuLCD::getTest(void)
{
  _lcd->clear(); //Autre subtilité, nous ne passons plus par un "." mais par "->"... Car on fait référence à l'objet pointé
  _lcd->setCursor(0,0); //Colonne, Ligne
  _lcd->print("Hello world");
}


Bien entendu, ça fonctionne parfaitement !

Je peux donc clore ce tread...

kamill

Tu utilises inutilement par des pointeurs.

C'est quasiment identique à la solution présentée par hbachetti au post #3 sauf que sa solution est beaucoup plus élégante.

hbachetti

Je n'avais pas stocké le lcd dans la classe sous forme de pointeur, mais de référence.
Cela permettait entre autres de ne pas transformer tout tes appels _lcd.clear(), _lcd.setCursor(), etc. en _lcd->clear(), lcd->setCursor, etc.
Mais bon, cela revient au même.
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

Go Up