PrécédentConclusion22 / 24SuivantDatasheet
3. Les microcontrôleurs

La programmation modulaire et orientée objet

La programmation modulaire et orientée objet

Principe

La programmation modulaire en C++ est une approche architecturale visant à découper le code en unités logiques indépendantes. Cette méthode favorise la réutilisabilité, la maintenabilité et la lisibilité des projets complexes. Au cœur de cette approche se trouve la Programmation Orientée Objet (POO), qui permet de modéliser le monde réel via des structures de données autonomes.

La notion d'objet et de classe

Pour maîtriser la POO, il est essentiel de distinguer la classe (le plan de construction) de l'objet (l'instance concrète).

Une classe définit un modèle contenant :

Prenons l'exemple d'une classe Véhicule.

Représentation schématique d'un objet 'Véhicule'
Représentation schématique d'un objet 'Véhicule'

L'héritage

La POO introduit le puissant mécanisme d'héritage. Il permet à une classe fille (dérivée) de récupérer automatiquement les attributs et méthodes d'une classe mère (de base), tout en pouvant les étendre ou les modifier.

Par exemple, pour créer une classe Voiture, il est inutile de redéfinir toutes les propriétés d'un véhicule. On déclare simplement que Voiture hérite de Véhicule. Ainsi, une Voiture possède nativement une couleur et peut avancer, tout en ajoutant ses spécificités (comme le nombre de portes).

Ce principe s'applique également au règne animal : une classe Mammifère peut hériter des caractéristiques générales de la classe Animal, tout en définissant des comportements spécifiques.

Relation d'héritage entre 'Véhicule' et 'Voiture'
Relation d'héritage entre 'Véhicule' et 'Voiture'

Structure des classes en C++

En C++, une classe est généralement répartie en deux fichiers distincts pour séparer l'interface (ce que l'on voit) de l'implémentation (comment cela fonctionne) :

⚠️

Attention : Une méthode déclarée mais non définie entraînera une erreur de lien (linker error) lors de la compilation.

Architecture typique d'une classe C++
Architecture typique d'une classe C++

Encapsulation et portée

L'un des piliers de la POO est l'encapsulation : on protège les données internes de la classe pour éviter qu'elles ne soient modifiées directement de l'extérieur. On utilise les mots-clés public (accessible partout) et private (accessible uniquement par la classe elle-même).

Voici un exemple moderne de déclaration de classe :

C++

Fichier de déclaration (Sensor.hpp)

#ifndef SENSOR_HPP #define SENSOR_HPP

class Sensor private: // Données privées : inaccessibles de l'extérieur int m_address; bool m_initialized;

public: // Constructeur : initialisation de l'objet Sensor(int address);

// Méthodes publiques : interface de la classe void init(); int read();

// Destructeur (optionnel ici, mais bonne pratique)  Sensor(); ;

#endif // SENSOR_HPP

💡

Les garde-fous \#ifndef \#define \#endif évitent les inclusions multiples. On peut aussi utiliser \#pragma once.

Implémentation des méthodes

Le fichier source (.cpp) contient le code réel des fonctions. L'opérateur de résolution de portée :: permet de lier la méthode à sa classe.

C++

Fichier d'implémentation (Sensor.cpp)

#include "Sensor.hpp"

// Initialisation dans le constructeur

Sensor::Sensor(int address) : m_address(address), m_initialized(false) // Code d'initialisation

void Sensor::init() { if (!m_initialized) // Logique d'initialisation matérielle m_initialized = true; }

int Sensor::read() if (!m_initialized) return -1; // Simulation de lecture return m_address * 10;

Sensor:: Sensor() // Nettoyage des ressources si nécessaire

Utilisation de l'objet

Pour utiliser la classe, on crée une instance (un objet) dans le programme principal. Notez l'utilisation du constructeur pour passer des paramètres dès la création.

C++

Utilisation dans le programme principal

#include "Sensor.hpp"
MySensor mySensor(42); // Création de l'objet avec initialisation de l'adresse
void setup() 
 // Création de l'objet avec initialisation de l'adresse Sensor mySensor(42);

// Appel de la méthode d'initialisation mySensor.init();

void loop() // Lecture de la valeur via l'interface publique int value = mySensor.read(); // Traitement de la valeur...

Directives du préprocesseur

Le préprocesseur traite le code avant la compilation. Il gère notamment l'inclusion de fichiers et la compilation conditionnelle.

Les directives principales sont :

C++

Garde-fou contre les inclusions multiples

#ifndef SENSOR_HPP 
#define SENSOR_HPP

// Contenu de la classe Sensor...

#endif

Cette structure garantit que le compilateur ne traite le contenu du fichier Sensor.hpp qu'une seule fois, même si celui-ci est inclus indirectement par plusieurs autres fichiers.

PrécédentConclusion22 / 24SuivantDatasheet