문제

서브 클래스 생성자에서 슈퍼 클래스 생성자를 호출하기위한 C ++ 규칙은 무엇입니까?

예를 들어, Java에서는 하위 클래스 생성자의 첫 번째 줄로 수행해야합니다 (그렇지 않은 경우 No -Arg 슈퍼 생성자에 대한 암시 적 호출이 가정됩니다. 누락 된 경우 컴파일 오류를 제공합니다). .

도움이 되었습니까?

해결책

기본 클래스 생성자는 논쟁이없는 경우 자동으로 귀하를 요구합니다. 인수로 슈퍼 클래스 생성자를 호출하려면 서브 클래스의 생성자 초기화 목록을 사용해야합니다. Java와 달리 C ++는 다중 상속을 지원하므로 (더 나은 또는 악화) 기본 클래스는 "super ()"대신 이름으로 언급되어야합니다.

class SuperClass
{
    public:

        SuperClass(int foo)
        {
            // do something with foo
        }
};

class SubClass : public SuperClass
{
    public:

        SubClass(int foo, int bar)
        : SuperClass(foo)    // Call the superclass constructor in the subclass' initialization list.
        {
            // do something with bar
        }
};

생성자의 초기화 목록에 대한 자세한 정보 여기 그리고 여기.

다른 팁

C ++에서는 생성자를 입력하기 전에 모든 슈퍼 클래스 및 멤버 변수에 대한 비 연락 생성자가 귀하에게 요청됩니다. 인수를 전달하려면 "생성자 체인"이라는 별도의 구문이 있습니다.

class Sub : public Base
{
  Sub(int x, int y)
  : Base(x), member(y)
  {
  }
  Type member;
};

이 시점에서 실행되는 일이 발생하면 이전에 건설을 완료 한 기지/회원은 소멸자를 불러 내고 예외는 발신자에게 다시 상환됩니다. 체인 중에 예외를 포착하려면 기능 시도 블록을 사용해야합니다.

class Sub : public Base
{
  Sub(int x, int y)
  try : Base(x), member(y)
  {
    // function body goes here
  } catch(const ExceptionType &e) {
    throw kaboom();
  }
  Type member;
};

이 형식에서는 시도 블록에 주목하십시오 ~이다 기능의 본문 안에있는 것이 아니라 기능의 본문; 이를 통해 함수 본문에서뿐만 아니라 암시 적 또는 명시 적 멤버 및 기본 클래스 초기화에 의해 발생 된 예외를 포착 할 수 있습니다. 그러나 함수 캐치 블록이 다른 예외를 던지지 않으면 런타임은 원래 오류를 재고합니다. 초기화 중 예외 할 수 없습니다 무시하십시오.

C ++에는 생성자의 초기화 목록이 있는데, 여기에는 기본 클래스의 생성자를 호출 할 수 있고 데이터 멤버를 초기화 해야하는 곳입니다. 초기화 목록은 결장을 따라 생성자 서명과 생성자의 본문 앞에 나온다. 클래스 A가 있다고 가정 해 봅시다.


class A : public B
{
public:
  A(int a, int b, int c);
private:
  int b_, c_;
};

그런 다음 B가 int를 취하는 생성자가 있다고 가정하면 A의 생성자가 다음과 같이 보일 수 있습니다.


A::A(int a, int b, int c) 
  : B(a), b_(b), c_(c) // initialization list
{
  // do something
}

보시다시피, 기본 클래스의 생성자는 초기화 목록에서 호출됩니다. 그런데 초기화 목록에서 데이터 구성원을 초기화하는 것은 추가 할당 비용을 절약하기 때문에 생성자 본체 내부에서 B_ 및 C_의 값을 할당하는 것이 좋습니다.

초기화 목록의 주문에 관계없이 클래스 정의에서 선언 된 순서로 데이터 구성원은 항상 초기화됩니다. 데이터 멤버가 서로 의존하는 경우 발생할 수있는 이상한 버그를 피하려면 항상 멤버의 순서가 초기화 목록과 클래스 정의에서 동일해야합니다. 같은 이유로 기본 클래스 생성자는 초기화 목록의 첫 번째 항목이어야합니다. 완전히 생략하면 기본 클래스의 기본 생성자가 자동으로 호출됩니다. 이 경우 기본 클래스에 기본 생성자가없는 경우 컴파일러 오류가 발생합니다.

모두가 초기화 목록을 통해 생성자 호출을 언급했지만, 부모 클래스의 생성자를 파생 된 멤버의 생성자의 본문에서 명시 적으로 호출 할 수 있다고 아무도 말하지 않았습니다. 질문을 참조하십시오 서브 클래스 생성자 본체에서 기본 클래스의 생성자 호출, 예를 들어. 요점은 파생 클래스 본문에서 부모 클래스 또는 슈퍼 클래스 생성자에 대한 명시 적 호출을 사용하는 경우 실제로 부모 클래스의 인스턴스를 만드는 것이며 파생 된 개체에서 부모 클래스 생성자를 호출하지 않습니다. . 파생 클래스 객체에서 부모 클래스 또는 슈퍼 클래스 생성자를 호출하는 유일한 방법은 파생 클래스 생성자 본문이 아닌 초기화 목록을 통과하는 것입니다. 따라서 "슈퍼 클래스 생성자 호출"이라고 불려서는 안됩니다. 누군가가 혼란 스러울 수 있기 때문에이 답을 여기에 두었습니다.

부모 생성자에게 값을 전달하는 유일한 방법은 초기화 목록을 통과하는 것입니다. 시작 목록은 다음과 같이 구현 된 다음 해당 클래스 생성자에게 전달할 클래스 및 값 목록을 구현합니다.

Class2::Class2(string id) : Class1(id) {
....
}

또한 부모 클래스에서 매개 변수를 사용하지 않는 생성자가있는 경우 자식 생성자 실행 전에 자동으로 호출됩니다.

인수가없는 생성자가있는 경우 파생 클래스 생성자가 실행되기 전에 호출됩니다.

인수가있는 기본 구성자를 호출하려면 파생 생성자에 다음과 같이 명시 적으로 작성해야합니다.

class base
{
  public:
  base (int arg)
  {
  }
};

class derived : public base
{
  public:
  derived () : base (number)
  {
  }
};

C ++에서 부모 생성자를 호출하지 않고 파생 수업을 구성 할 수 없습니다. ARG가 아닌 경우 자동으로 발생합니다. 위에 표시된대로 파생 생성자를 직접 호출하거나 코드가 컴파일되지 않으면 발생합니다.

기본 생성자에 기본 매개 변수가있는 경우 기본 클래스가 자동으로 호출됩니다.

using namespace std;

class Base
{
    public:
    Base(int a=1) : _a(a) {}

    protected:
    int _a;
};

class Derived : public Base
{
  public:
  Derived() {}

  void printit() { cout << _a << endl; }
};

int main()
{
   Derived d;
   d.printit();
   return 0;
}

출력은 다음과 같습니다. 1

CDerived::CDerived()
: CBase(...), iCount(0)  //this is the initialisation list. You can initialise member variables here too. (e.g. iCount := 0)
    {
    //construct body
    }

클래스가 여러 클래스에서 파생 될 때 생성자 호출 순서를 언급 한 사람은 없습니다. 시퀀스는 클래스를 도출하는 동안 언급되어 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top