2
votes

Lorsque j'appelle une fonction dans une classe enfant, il appelle à la place la fonction de classe parent

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;
}


0 commentaires

4 Réponses :


1
votes

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;
    }
};


1 commentaires

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é.



3
votes

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é.


1 commentaires

Terme de recherche pour plus d'informations tranchage d'objet .



2
votes

Votre code souffre de deux problèmes:

  1. 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.

  2. 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;
}


0 commentaires

2
votes

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().


0 commentaires