Подтвердить что ты не робот

Как я могу инициализировать переменные-члены базового класса в конструкторе производного класса?

Почему я не могу это сделать?

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

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

};
4b9b3361

Ответ 1

Вы не можете инициализировать a и b в b, потому что они не являются членами b. Они являются членами a, поэтому только a может их инициализировать. Вы можете сделать их общедоступными, а затем выполнить назначение в b, но это не рекомендуется, так как это разрушит инкапсуляцию. Вместо этого создайте конструктор в a, чтобы разрешить b (или любой подкласс a) инициализировать их:

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 constructor, initializing a and b in A to 0.
    {
    } 
};

Ответ 2

Оставляя в стороне тот факт, что они являются private, поскольку a и b являются членами A, они должны инициализироваться конструкторами A, а не некоторыми другими конструкторами классов (производными или нет).

Пытаться:

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

Ответ 3

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

Это рабочий пример, если вы хотите инициализировать элементы данных базового класса, присутствующие в объекте класса Derived, тогда как вы хотите, чтобы эти значения взаимодействовали с помощью вызова конструктора класса Derived.

Ответ 4

Почему-то никто не перечислил самый простой способ:

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

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

};

Вы не можете получить доступ к базовым членам в списке инициализатора, но сам конструктор, как и любой другой метод-член, может получить доступ к public и protected членам базового класса.

Ответ 5

Хотя это полезно в редких случаях (если бы это было не так, язык разрешил бы его напрямую), посмотрите на Base from Идиома участника. Это не решение, свободное от кода, вам нужно добавить дополнительный слой наследования, но он выполняет свою работу. Чтобы избежать кода шаблона, вы можете использовать повысить эффективность

Ответ 6

Почему ты не можешь это сделать? Поскольку язык не позволяет инициализировать список инициализаторов базового класса в производном классе.

Как вы можете это сделать? Вот так:

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

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

Ответ 7

Если вы не укажете видимость для члена класса, по умолчанию используется "private". Вы должны сделать ваши члены частными или защищенными, если вы хотите получить к ним доступ в подклассе.

Ответ 8

Агрегатные классы, такие как A в вашем примере (*), должны иметь своих членов общедоступными и не иметь определяемых пользователем конструкторов. Они инициализируются списком инициализаторов, например. A a {0,0}; или в вашем случае B() : A({0,0}){}. Члены базового агрегатного класса не могут быть индивидуально инициализированы в конструкторе производного класса.

(*) Чтобы быть точным, как было правильно сказано, оригинал class A не является совокупностью из-за личных нестатических элементов