Surcharge des opérateurs [] et ()
Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 45 sur 104.
L'opérateur d'indice ([]) permet à votre classe de se comporter comme un tableau, offrant un accès indexé aux éléments. L'opérateur d'appel de fonction (()) transforme les objets en entités appelables, connues sous le nom de foncteurs.
Voici un simple wrapper de tableau avec l'opérateur d'indice :
class IntArray {
int* data;
size_t size;
public:
IntArray(size_t s) : size(s), data(new int[s]()) {}
~IntArray() { delete[] data; }
int& operator[](size_t index) {
return data[index];
}
const int& operator[](size_t index) const {
return data[index];
}
};Notez que nous fournissons deux versions : l’une renvoie une référence non const (permettant la modification), et la version const fonctionne avec les objets const. Cela vous permet d’écrire arr[0] = 5; pour lire et écrire.
L'opérateur d'appel de fonction crée des objets qui peuvent être « appelés » comme des fonctions :
class Multiplier {
int factor;
public:
Multiplier(int f) : factor(f) {}
int operator()(int value) const {
return value * factor;
}
};
Multiplier triple(3);
int result = triple(10); // Retourne 30Les foncteurs sont puissants car ils peuvent maintenir un état entre les appels, contrairement aux fonctions classiques. Ils sont couramment utilisés avec les algorithmes de la STL où vous avez besoin d'un comportement personnalisable qui mémorise des valeurs de configuration.
Défi
FacileConstruisons une classe ScoreTracker qui combine à la fois l’opérateur d’indice et l’opérateur d’appel de fonction. Cette classe stockera les scores des joueurs et vous permettra d’y accéder par indice à l’aide de [], tout en agissant comme un foncteur qui applique un multiplicateur de bonus à tout score que vous lui transmettrez.
Vous allez créer deux fichiers pour organiser votre code :
ScoreTracker.h: définissez une classeScoreTrackerqui gère un tableau de scores des joueurs et peut appliquer des bonus. Votre classe doit comporter :- un tableau
int*alloué dynamiquement pour stocker les scores - un membre
size_tindiquant le nombre de scores - un membre
doublepour le multiplicateur de bonus - un constructeur qui prend la taille et le multiplicateur de bonus, en initialisant tous les scores à 0
- un destructeur qui libère correctement la mémoire dynamique
- l’opérateur d’indice
[](dans ses versions const et non const) pour accéder aux scores par indice - l’opérateur d’appel de fonction
()qui prend un scoreintet renvoie le score multiplié par le multiplicateur de bonus (sous forme deint) - une méthode
getSize()qui renvoie le nombre de scores
L’opérateur d’indice non const renvoie une référence afin que vous puissiez écrire
tracker[0] = 100;. La version const permet un accès en lecture seule pour les objets const. L’opérateur d’appel de fonction doit être marquéconst, puisqu’il ne modifie pas l’état de l’objet.- un tableau
main.cpp: lisez les entrées suivantes (chacune sur une ligne distincte) :- Nombre de joueurs (taille)
- Multiplicateur de bonus (sous forme de double)
- Scores de chaque joueur (un par ligne, au nombre indiqué par la taille)
- Un score de test auquel appliquer le bonus
Créez un
ScoreTracker, utilisez l’opérateur d’indice pour stocker le score de chaque joueur, puis affichez tous les scores. Enfin, utilisez l’opérateur d’appel de fonction pour calculer le score auquel le bonus a été appliqué.Format de sortie :
Player 0: <score> Player 1: <score> ... Bonus applied to <test_score>: <result>
Par exemple, avec 3 joueurs, un multiplicateur de 1.5, des scores de 100, 200 et 150, ainsi qu’un score de test de 80 :
Player 0: 100
Player 1: 200
Player 2: 150
Bonus applied to 80: 120Utilisez std::stoi() et std::stod() pour la conversion des entrées. N’oubliez pas les gardes d’inclusion dans votre fichier d’en-tête.
Essayez vous-même
#include <iostream>
#include <string>
#include "ScoreTracker.h"
using namespace std;
// TODO: Implémenter le constructeur de ScoreTracker
ScoreTracker::ScoreTracker(size_t size, double multiplier) {
// TODO: Initialiser les membres et allouer le tableau dynamique
// Initialiser tous les scores à 0
}
// TODO: Implémenter le destructeur de ScoreTracker
ScoreTracker::~ScoreTracker() {
// TODO: Nettoyer la mémoire dynamique
}
// TODO: Implémenter l'opérateur d'indice (subscript) non-const
// TODO: Implémenter l'opérateur d'indice (subscript) const
// TODO: Implémenter l'opérateur d'appel de fonction
// TODO: Implémenter la méthode getSize
size_t ScoreTracker::getSize() const {
// TODO: Retourner le nombre de scores
}
int main() {
string line;
// Lire le nombre de joueurs
getline(cin, line);
size_t numPlayers = stoi(line);
// Lire le multiplicateur de bonus
getline(cin, line);
double multiplier = stod(line);
// TODO: Créer ScoreTracker avec numPlayers et multiplier
// TODO: Lire les scores pour chaque joueur et les stocker en utilisant l'opérateur d'indice
// TODO: Lire le score de test
// TODO: Afficher tous les scores des joueurs au format : "Player X: <score>"
// TODO: Afficher le résultat du bonus appliqué au format : "Bonus applied to <test_score>: <result>"
return 0;
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesGénération et compilation en C++Fichiers d’en-tête et fichiers sourceEspaces de noms et portéeIntroduction à la POO en C++Classes et objetsLe pointeur « this »Méthodes (fonctions membres)Attributs (membres de données)Bases des constructeurs et destructeursRécapitulatif - Calculatrice simple4Propriétés de classe
Membres d’instance et statiquesAccesseurs et mutateursFonctions membres constMot-clé mutableMéthodes et variables statiquesFonctions et classes amiesRécapitulatif - Gestionnaire de compte bancaire7Héritage
Héritage de baseNiveaux d’accès de l’héritageOrdre d’appel des constructeurs et destructeursRedéfinition des méthodesFonctions virtuelles et VTableHéritage multipleHéritage virtuelRécapitulatif : hiérarchie des employés10Vue d’ensemble de la STL
Vue d’ensemble et philosophie de la STLConteneurs de la STLItérateursAlgorithmes de la STLFoncteurs et expressions lambdaRécapitulatif - fréquence des mots13Modèles de conception, partie 1
Introduction aux modèles de conceptionModèle SingletonFabrique et fabrique abstraiteModèle BuilderModèle ObserverModèle Strategy2Gestion de la mémoire
Mémoire de pile ou de tasPointeurs et référencesMémoire dynamique (new/delete)Pointeurs intelligents en C++RAII en C++Récapitulatif - Gestionnaire de tableaux dynamiques5Encapsulation
Spécificateurs d’accès en C++Spécificateurs d’accès en profondeurMasquage de l’informationStruct vs classeClasses imbriquées et internesRécapitulatif - Système de gestion des dossiers étudiants8Polymorphisme
Polymorphisme à la compilation vs à l’exécutionSurcharge de fonctionsRetour sur les fonctions virtuellesFonctions virtuelles puresClasses abstraitesConception d’interfaces en C++Conversion dynamique et RTTIRécapitulatif - Calculateur de formes3Constructeurs et destructeurs
Constructeur par défautConstructeur paramétréConstructeur de copieConstructeur de déplacementListes d’initialisation des constructeursConstructeurs déléguésApprofondissement des destructeursRègle des trois / cinq / zéroRécapitulatif - Classe String6Surcharge des opérateurs
Introduction à la surcharge des opérateursSurcharge des opérateurs arithmétiquesSurcharge des opérateurs de comparaisonOpérateurs de fluxSurcharge de l’opérateur d’affectationSurcharge des opérateurs [] et ()Opérateurs de conversion de typeRécapitulatif – Classe Matrix9Templates
Templates de fonctionsTemplates de classesSpécialisation des templatesTemplates variadiquesBases de SFINAE et des traits de typesRécapitulatif - Conteneur génériqueEntraînez-vous par vous-même : Compilateur C++ en ligne