web-dev-qa-db-fra.com

Comment puis-je initialiser des variables de membre de classe de base dans un constructeur de classe dérivée?

Pourquoi je ne peux pas faire ça?

class A
{
public:
    int a, b;
};

class B : public A
{
    B() : A(), a(0), b(0)
    {
    }

};
99
amrhassan

Vous ne pouvez pas initialiser a et b dans B car ils ne sont pas membres de B. Ils sont membres de A, donc seul A peut les initialiser. Vous pouvez les rendre publics, puis effectuez une affectation dans B, mais ce n'est pas une option recommandée car cela détruirait l'encapsulation. Au lieu de cela, créez un constructeur dans A pour permettre à B (ou toute sous-classe de A) de les initialiser:

class A 
{
protected:
    A(int a, int b) : a(a), b(b) {} // Accessible to derived classes
    // Change "protected" to "public" to allow others to instantiate A.
private:
    int a, b; // Keep these variables private in A
};

class B : public A 
{
public:
    B() : A(0, 0) // Calls A's constructor, initializing a and b in A to 0.
    {
    } 
};
115
In silico

Laissant de côté le fait qu’ils sont private, puisque a et b sont membres de A, ils doivent être initialisés par A par les constructeurs, pas par les constructeurs d'une autre classe (dérivés ou non).

Essayer:

class A
{
    int a, b;

protected: // or public:
    A(int a, int b): a(a), b(b) {}
};

class B : public A
{
    B() : A(0, 0) {}
};
24
NPE

D'une manière ou d'une autre, personne n'a énuméré le moyen le plus simple:

class A
{
public:
    int a, b;
};

class B : public A
{
    B()
    {
        a = 0;
        b = 0;
    }

};

Vous ne pouvez pas accéder aux membres de base de la liste des initialiseurs, mais le contrôleur lui-même, comme toute autre méthode membre, peut accéder aux membres public et protected de la classe de base.

3
Violet Giraffe
# include<stdio.h>
# include<iostream>
# include<conio.h>

using namespace std;

class Base{
    public:
        Base(int i, float f, double d): i(i), f(f), d(d)
        {
        }
    virtual void Show()=0;
    protected:
        int i;
        float f;
        double d;
};


class Derived: public Base{
    public:
        Derived(int i, float f, double d): Base( i, f, d)
        {
        }
        void Show()
        {
            cout<< "int i = "<<i<<endl<<"float f = "<<f<<endl <<"double d = "<<d<<endl;
        }
};

int main(){
    Base * b = new Derived(10, 1.2, 3.89);
    b->Show();
    return 0;
}

C'est un exemple de travail dans le cas où vous souhaitez initialiser les membres de données de la classe Base présents dans l'objet de la classe Derived, alors que vous souhaitez pousser ces valeurs s'interfaçant via l'appel du constructeur de la classe Derived.

2
manish srivastava

Bien que cela soit utile dans de rares cas (si ce n'était pas le cas, le langage l'aurait permis directement), jetez un coup d'œil à Base from Member idiom . Ce n'est pas une solution sans code, il vous faudrait ajouter une couche supplémentaire d'héritage, mais le travail est fait. Pour éviter le code passe-partout, vous pouvez utiliser implémentation de boost

1

Pourquoi ne peux-tu pas le faire? Parce que le langage ne vous permet pas d'initialiser les membres d'une classe de base dans la liste d'initialisation de la classe dérivée.

Comment pouvez-vous y arriver? Comme ça:

class A
{
public:
    A(int a, int b) : a_(a), b_(b) {};
    int a_, b_;
};

class B : public A
{
public:
    B() : A(0,0) 
    {
    }
};
0
John Dibling