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



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



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

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

};
464   8  

8 ответов:

вы не можете инициализировать 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's constructor, initializing a and b in A to 0.
    {
    } 
};

оставляя в стороне тот факт, что они являются 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) {}
}

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

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

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

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

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

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

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

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

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

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

};

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

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

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

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

Comments

    Ничего не найдено.