program story

파생 클래스 생성자에서 기본 클래스 멤버 변수를 어떻게 초기화 할 수 있습니까?

inputbox 2020. 8. 15. 09:12
반응형

파생 클래스 생성자에서 기본 클래스 멤버 변수를 어떻게 초기화 할 수 있습니까?


왜 이렇게 할 수 없습니까?

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

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

};

멤버가 아니기 때문에 abin을 초기화 할 수 없습니다 . 의 멤버 이므로 초기화 가능합니다. 공개로 설정 한 다음에서 할당 할 수 있지만 캡슐화를 파괴 할 수 있으므로 권장되는 옵션이 아닙니다. 대신에 생성자 만들 수 있도록 (또는 서브 클래스 )을 초기화를 :BBAABABA

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

어쨌든 아무도 가장 간단한 방법을 나열하지 않았습니다.

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

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

};

You can't access base members in the initializer list, but the conmstructor itself, just as any other member method, may access public and protected members of the base class.


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

It's a working example in case you want to initialize the Base class data members present in the Derived class object, whereas you want to push these values interfacing via Derived class constructor call.


While this is usefull in rare cases (if that was not the case, the language would've allowed it directly), take a look at the Base from Member idiom. It's not a code free solution, you'd have to add an extra layer of inheritance, but it gets the job done. To avoid boilerplate code you could use boost's implementation


Why can't you do it? Because the language doesn't allow you to initializa a base class' members in the derived class' initializer list.

How can you get this done? Like this:

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

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

If you don't specify visibility for a class member, it defaults to "private". You should make your members private or protected if you want to access them in a subclass.


Aggregate classes, like A in your example(*), must have their members public, and have no user-defined constructors. They are intialized with initializer list, e.g. A a {0,0}; or in your case B() : A({0,0}){}. The members of base aggregate class cannot be individually initialized in the constructor of the derived class.

(*) To be precise, as it was correctly mentioned, original class A is not an aggregate due to private non-static members

참고URL : https://stackoverflow.com/questions/7405740/how-can-i-initialize-base-class-member-variables-in-derived-class-constructor

반응형