web-dev-qa-db-fra.com

Appel du constructeur de classe de base à partir du constructeur de classe dérivé

J'ai une question:

Disons que j'ai à l'origine ces classes que je ne peux pas changer (disons parce qu'elles proviennent d'une bibliothèque que j'utilise):

class Animal_
{
public:
    Animal_();
    int getIdA()
    {
        return idA;
    };
    string getNameA()
    {
        return nameA;
    }
private:
    string nameA;
    int idA;
}

class Farm
{
public :
    Farm()
    {
        sizeF=0;
    }
    Animal_* getAnimal_(int i)
    {
        return animals_[i];
    }
    void addAnimal_(Animal_* newAnimal)
    {
        animals_[sizeF]=newAnimal;
        sizeF++;
    }

private:
    int sizeF;
    Animal_* animals_[max];
}

Mais alors j'avais besoin d'une classe où j'ajoute juste quelques champs alors j'ai fait ceci:

class PetStore : public Farm
{
public :
    PetStore()
    {
     idF=0;
    };
private:
    int idF;
    string nameF;
}

Mais je ne peux pas initialiser ma classe dérivée, je veux dire que j'ai fait cet héritage pour pouvoir ajouter des animaux à mon PetStore mais maintenant puisque sizeF est privé, comment puis-je faire cela? Je pense que dans le constructeur par défaut de PetStore, je peux appeler Farm () ... donc une idée?

25
Joy

Le constructeur de PetStore appellera un constructeur de Farm; il n'y a aucun moyen de l'empêcher. Si vous ne faites rien (comme vous l'avez fait), il appellera le constructeur par défaut (Farm()); si vous devez passer des arguments, vous devrez spécifier la classe de base dans la liste d'initialisation:

PetStore::PetStore()
    : Farm( neededArgument )
    , idF( 0 )
{
}

(De même, le constructeur de PetStore appellera le constructeur de nameF. Le constructeur d'une classe toujours appelle les constructeurs de toutes ses classes de base et de toutes ses membres.)

61
James Kanze

Tout d'abord, un PetStore n'est pas une batterie de serveurs.

Passons à autre chose. En fait, vous n'avez pas besoin d'accéder aux membres privés, vous avez tout ce dont vous avez besoin dans l'interface publique:

Animal_* getAnimal_(int i);
void addAnimal_(Animal_* newAnimal);

Ce sont les méthodes auxquelles vous avez accès et ce sont celles que vous devez utiliser.

Je veux dire que j'ai fait cet héritage pour pouvoir ajouter des animaux à mon PetStore, mais maintenant, comme sizeF est privé, comment puis-je le faire ??

Simple, vous appelez addAnimal. C'est public et il incrémente également sizeF.

Notez également que

PetStore()
{
 idF=0;
};

est équivalent à

PetStore() : Farm()
{
 idF=0;
};

c'est-à-dire que le constructeur de base est appelé, les membres de base sont initialisés.

13
Luchian Grigore

Le constructeur de classe de base est déjà appelé automatiquement par votre constructeur de classe dérivée. En C++, si la classe de base a un constructeur par défaut (ne prend aucun argument, peut être généré automatiquement par le compilateur!), Et que le constructeur de classe dérivée n'appelle pas un autre constructeur de classe de base dans sa liste d'initialisation, le constructeur par défaut être appelé. C'est à dire. votre code équivaut à:

class PetStore: public Farm
{
public :
    PetStore()
    : Farm()     // <---- Call base-class constructor in initialision list
    {
     idF=0;
    };
private:
    int idF;
    string nameF;
}
5
Michael Wild

mais je ne peux pas initialiser ma classe dérivée, je veux dire que j'ai fait cet héritage afin que je puisse ajouter des animaux à mon PetStore mais maintenant puisque sizeF est privé, comment puis-je faire ça ?? donc je pense que peut-être dans le constructeur par défaut de PetStore je peux appeler Farm () ... donc n'importe quelle idée ???

Pas de panique.

Le constructeur de la ferme sera appelé dans le constructeur de PetStore, automatiquement .

Voir les règles d'appel d'héritage de classe de base: Quelles sont les règles pour appeler le constructeur de la superclasse?

2
Klaim