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


123

왜 이렇게 할 수 없습니까?

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

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

};

7
당신이 묻는 이유는 당신이 그렇게 할 수있는 언어 설계 질문이다, 또는 당신이 요구하는 방법 해당 언어의 한계를 해결할 수 있나요?
Rob Kennedy

기본 생성자를 사용하지 않고 내가 알지 못하는 특별한 방법이 있다고 생각했습니다.
amrhassan 2011 년

기본 클래스 멤버는 파생 클래스 생성자가 실행될 때 이미 초기화되었습니다. 당신은 수 지정 이 액세스 할 수있는 경우, 그들을, 또는 그들을 위해 setter를 호출하거나, 적절한가있는 경우 당신은 기본 클래스 생성자에 대한 값을 제공 할 수 있습니다. 고안된 클래스에서 할 수없는 한 가지는 초기화입니다.
Marquis of Lorne

답변:


143

의 멤버가 아니기 때문에 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.
    {
    } 
};

32
귀하의 예는 정확하지만 설명은 오해의 소지가 있습니다. 그것은하지 당신이 할 수없는의 초기화 abB::B()그들이 개인 때문이다. 의 멤버가 아니기 때문에 초기화 할 수 없습니다 class B. 당신이 그 (것)들을 공개 또는 보호 된 경우에 당신은 수 지정 의 몸을 B::B().
R Samuel Klatchko 2011 년

2
또한 솔루션은 클래스 A를 집계되지 않으므로 중요 할 수 있으므로 언급해야합니다.
Gene Bushuyev 2011 년

1
@R Samuel Klatchko : 좋은 지적입니다. 대답을 작성할 때 처음에는 "You ca n't access aand b..."라고 입력 하고 나머지 문장이 의미가 있는지 확인하지 않고 "You ca n't initialize ..."로 변경했습니다. 게시물이 수정되었습니다.
In silico 2011 년

1
@Gene Bushuyev : 질문의 원본 코드의 클래스는 아니다 집계 (비 정적 개인 회원이있다)
dribeas - 데이비드 로드리게스

@David-맞습니다. 이것은 사용자의 오류이며, 사용자의 의도를 파악하려고 노력하고 있습니다.
Gene Bushuyev 2011 년

26

옆으로가 있다는 사실 떠나 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) {}
};

7

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

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

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

};

이니셜 라이저 목록의 기본 멤버에 액세스 할 수 없지만 다른 멤버 메서드와 마찬가지로 생성자 자체 가 기본 클래스의 publicprotected멤버에 액세스 할 수 있습니다 .


1
좋은. 이런 식으로하는 데 단점이 있습니까?
Wander3r

2
@SaileshD : 값 비싼 생성자로 객체를 초기화하는 경우있을 수 있습니다. 의 인스턴스 B가 할당 될 때 먼저 기본값으로 초기화 된 다음 B의 생성자 내부에 할당됩니다 . 그러나 컴파일러가 여전히 이것을 최적화 할 수 있다고 생각합니다.
Violet Giraffe

1
내부에서 class A우리는에 의존 할 수 ab초기화된다. class C : public A예를 들어 의 모든 구현은 호출하는 a=0;것을 잊고 a초기화되지 않은 상태로 둘 수 있습니다 .
Sparkofska

@Sparkofska, 매우 사실입니다. 필드를 선언 할 때 내부 ( class A { int a = 0;};) 또는 기본 클래스의 생성자에서 필드를 기본 초기화하는 것이 가장 좋습니다 . 서브 클래스는 필요에 따라 생성자에서 다시 초기화 할 수 있습니다.
Violet Giraffe

1
@ Wander3r 또 다른 단점은 모든 클래스에 할당 연산자가있는 것은 아니라는 것입니다. 일부는 구성 만 가능하지만 할당 할 수는 없습니다. 그러면 완료됩니다 ...
Martin Pecka

2
# 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 클래스 개체에있는 Base 클래스 데이터 멤버를 초기화하려는 경우 작동하는 예제입니다.



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

-1

클래스 멤버에 대한 가시성을 지정하지 않으면 기본값은 "private"입니다. 하위 클래스에서 액세스하려면 구성원을 비공개 또는 보호해야합니다.


-1

example (*)의 A와 같은 집계 클래스에는 멤버가 public이어야하며 사용자 정의 생성자가 없어야합니다. 예를 들어 A a {0,0};또는 귀하의 경우에는 이니셜 라이저 목록으로 초기화됩니다 B() : A({0,0}){}. 기본 집계 클래스의 멤버는 파생 클래스의 생성자에서 개별적으로 초기화 할 수 없습니다.

(*) 정확하게 언급했듯이 원본 class A은 비공개 비 정적 멤버로 인해 집계가 아닙니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.