2016-08-03 5 views
0

나는 Understanding virtual base classes and constructor calls을 찾고 있었고 가장 파생 된 클래스가 최상위 기본 클래스의 기본 생성자를 직접 호출한다는 것을 알고 있습니다. 하지만 기본 기본 생성자를 호출하지 않는 방법이 있습니까? 내 문제에 대한가상 기본 클래스의 기본 생성자를 사용하지 마십시오

한 예로,

#include <iostream> 
#include <cstdint> 

////// BEGIN LIBRARY CODE 
class A 
{ 
public: 
    A() 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 

    A(int) 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 

class B : virtual public A 
{ 
public: 
    B() 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 

class C: virtual public A 
{ 
public: 
    C() 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 

class D: public B, public C 
{ 
public: 
    D(int x) : A(x), B(), C() // ok. works as expected 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 
////// END LIBRARY CODE 


////// USER CODE BEGINS 

class E: public D 
{ 
public: 
    E() : D(42) // problem, invokes A(), not A(int) 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 

    E(int x) : D(x) // same problem 
    { 
     std::cout << __PRETTY_FUNCTION__ << '\n'; 
    } 
}; 
////// USER CODE ENDS 

int main() 
{ 
    D d(1); 
    E e1,e2(42); 
} 

출력

A::A(int) 
B::B() 
C::C() 
D::D(int) 
A::A() 
B::B() 
C::C() 
D::D(int) 
E::E() 
A::A() 
B::B() 
C::C() 
D::D(int) 
E::E(int) 

문제 :

내가 약 D 건설 신경에 E를 원한다. 그러나 처음에 설명에서, 나는 항상 아무리 짧은에서 클래스 D

E() : A(42), D(42) // works, but undesirable 
{ 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
} 

E(int x) : A(x), D(x) // this works, but undesirable 
{ 
    std::cout << __PRETTY_FUNCTION__ << '\n'; 
} 

를 업데이트하는 방법을 기본 생성자를 사용하지 않습니다, 아래 A::A(int)를 추가하지 않을 경우, 나는 사용자 코드를 원하지 않는 class E 라이브러리 코드 class D을 연장

  • 이 위 같은 내 예제에서 클래스 D으로 상속 체인에 "중간"클래스 수행 할 수있는 방법으로, 거기에 class A 구성 매개 변수 정도 ... 지정해야합니다 가장 파생 된 수업을 그렇게 할 필요가 없도록 완화 시키십시오.
+1

당신은 저자입니다. 생성자 초기화 목록에서 원하는 초기화를 지정할 수 있습니다. –

+1

'top-base'는 유효한 식별자가 아닙니다. 실제 코드를 게시하십시오. –

+0

'top-base' 대신에'A'를 의미할까요? –

답변

1

최상위 클래스의 생성자는 모든 가상 기반의 생성자를 호출합니다. 그러나 직접적인 비 가상베이스 생성자를 호출하는 것과 다르지 않습니다. 명시 적 생성자 호출을 사용하면 컴파일러에서 사용할 것입니다. 그렇지 않으면 기본 생성자가 사용됩니다. 그래서 대답은 '아니오'입니다. 기본 생성자가 적절하지 않으면 E의 A 생성자를 호출 할 수 없습니다.

+1

디자인을 변경함으로써 아마도'D' 클래스는 직접 상속 대신에 데이터 멤버와 포워딩을 사용할 수 있으며, 그 데이터 멤버는'B'와'C'를 상속받은 클래스 일 수 있습니다. –

+0

@ Cheersandhth.-Alf 내가 OP 코드를 읽기 쉽도록 수정하고 질문과 일치하게 만들 때, 그것은 내가 생각한 것입니다. – WhozCraig

+0

나는 그 질문이 무엇에 관한 것인지에 달려 있다고 생각합니다. 디자인 변경은 코딩 문제에 대한 적절한 해결 방법이 아니지만 코딩 문제로 인해 디자인 문제가 있음을 나타낼 수 있습니다. 그러나 문제의 디자인이 주어지면 대답은 간단합니다. –

관련 문제