Je travaille sur un projet où j'ai un éventail de classes pour enfants. Je souhaite appeler une fonction enfant remplacée à partir du tableau, mais à la place, elle appelle la fonction parent.
I'm childOne! I'm childTwo!
La sortie que j'obtiens est
I'm the parent! I'm the parent!
Où se trouve la sortie que je veux
#include <iostream> class Parent { public: Parent(){} void print() { std::cout << "I'm the parent!" << std::endl; } }; class ChildOne : public Parent { public: ChildOne(){} void print() { std::cout << "I'm childOne!" << std::endl; } }; class ChildTwo : public Parent { public: ChildTwo() {} void print() { std::cout << "I'm childTwo!" << std::endl; } }; int main(int argc, char const *argv[]) { Parent arr[] = {ChildOne(), ChildTwo()}; int n = 2; for(int i = 0; i < n; i++) { arr[i].print(); } return 0; }
4 Réponses :
Vous devrez spécifier la fonction parente comme virtual
, et les fonctions enfants doivent utiliser le mot-clé override
.
class Parent { public: Parent(){} virtual void print() { std::cout << "I'm the parent!" << std::endl; } }; class ChildOne : public Parent { public: ChildOne(){} void print() override { std::cout << "I'm childOne!" << std::endl; } }; class ChildTwo : public Parent { public: ChildTwo() {} void print() override { std::cout << "I'm childTwo!" << std::endl; } };
Le code de l'OP souffre de "tranchage d'objet" lors du remplissage du tableau, ce n'est donc qu'une partie du correctif nécessaire. Le tableau doit également être corrigé.
Vous convertissez implicitement toutes vos instances en type Parent
lorsque vous les stockez dans ce tableau typé. Puisque vous utilisez la répartition statique, vous allez toujours appeler la méthode sur le type de base vers lequel vous avez (implicitement) abaissé.
Terme de recherche pour plus d'informations tranchage d'objet .
Votre code souffre de deux problèmes:
vous ne remplacez pas du tout print ()
, car ce n'est pas virtuel
. Vous ne faites que la surcharger dans chaque classe enfant, cachant la méthode du parent.
vous découpez vos objets lors de leur stockage dans votre tableau. Donc, peu importe si print ()
est virtuel, car il n'y a pas d'objets enfants dans le tableau, seulement des objets parents. Le polymorphisme fonctionne correctement uniquement lors de l'utilisation de pointeurs / références aux classes de base.
Essayez plutôt ceci:
#include <iostream> class Parent { public: Parent(){} virtual void print() { std::cout << "I'm the parent!" << std::endl; } }; class ChildOne : public Parent { public: ChildOne(){} void print() override { std::cout << "I'm childOne!" << std::endl; } }; class ChildTwo : public Parent { public: ChildTwo() {} void print() override { std::cout << "I'm childTwo!" << std::endl; } }; int main() { ChildOne c1; ChildTwo c2; Parent* arr[] = {&c1, &c2}; int n = 2; for(int i = 0; i < n; i++) { arr[i]->print(); } return 0; }
Premièrement, la fonction membre de Parent
doit être virtual
.
std::unique_ptr<Parent> arr[] = {new ChildOne(), new ChildTwo()};
Ensuite, les enfants doivent la remplacer. Dans C ++ 11 et versions ultérieures, il est conseillé d'utiliser override
for(int i = 0; i < 2; i++) { arr[i]->print(); } for(int i = 0; i < 2; i++) // to avoid a memory leak { delete arr[i]; } // don't use elements of `arr` here
La deuxième chose à adresser est que votre code dans main ()
Parent *arr[] = {new ChildOne(), new ChildTwo()};
initialise deux objets Parent
en les découpant, c'est-à-dire que arr [0]
et arr [1]
sont tous deux de type Parent
, pas de ChildOne
ou ChildTwo
respectivement.
Pour adresser cela, il faut que arr
être un tableau de pointeurs, et initialisé en conséquence.
Parent arr[] = {ChildOne(), ChildTwo()};
qui peut être suivi avec
class ChildOne : public Parent { public: ChildOne(){} void print() override {std::cout << "I'm childOne!" << std::endl;}; };
Une meilleure façon ( C ++ 11 et versions ultérieures) consiste à écrire main ()
consiste à utiliser std :: unique_ptr
à partir de l'en-tête standard
)
class Parent { public: Parent(){} virtual void print() {std::cout << "I'm the parent!" << std::endl;}; };
qui permet de supprimer la boucle pour libérer les éléments de arr
. Dans C ++ 14 et versions ultérieures, les objets dans arr
peuvent être créés en utilisant std::make_unique()
.