2014-01-14 4 views
4

참고 : C++ 11 Delegated Constructor Pure Virtual Method & Function Calls -- Dangers? 복제본이 아닙니다. 이 다른 질문은 실제로이 경우에 대한 해결책을 제시하지 않는 개념적으로 유사한 문제를 나타냅니다. (이것은 어떤 컴파일러에 경고와 함께 컴파일 않지만)C++ 11 생성자 상속 및 순수 가상 메서드

#include <iostream> 
using std::cout; 
using std::endl; 

class Base { 
    virtual void init() = 0; // a hook function 
    public: 
    Base(int a, int b) { /* ... */ init(); } 
    Base(char a, int b) { /* ... */ init(); } 
    Base(char a, int b, double* c) { /* ... */ init(); } 
    /* etc. Dozens of constructors */ 
};  

class Derived1 : public Base {  
    void init() { cout << "In Derived1::init()" << endl; }  
    public:  
    using Base::Base;  
};  

class Derived2 : public Base {  
    void init() { cout << "In Derived2::init()" << endl; }  
    public:  
    using Base::Base;  
};  

int main() { 
    Derived1 d1(1, 2); 
    Derived2 d2('a', 3); 
    return 0; 
} 

이 코드는 분명히 실행되지 않습니다

다음 프로그램을 고려하십시오. 문제는 이런 종류의 패턴을 구현하는 가장 좋은 방법은 무엇입니까? 수십 개의 파생 클래스와 수십 개의 생성자가 Base에 있다고 가정하면 파생 클래스에서 Base 생성자를 다시 구현합니다 (파생 생성자의 본문에서 기본 생성자와 init()에 대한 호출을 사용)은 실제로 이상적이 아닙니다.

+1

많은 개행 문자와 빈 덧글을 삭제하여 쉽게 이해할 수 있습니다. 비교 가능한 작은 브라우저 창에서 전체 코드를 찾습니다. – dornhege

답변

2

해당 코드는 파생 클래스 생성자에서 이동해야하며 개체가 파생 된 형식이 될 때까지 실행할 수 없습니다.

하지만 당신은 한 번 완벽한 전달을 사용하는 모든 생성자에 추가 할 수 있습니다 :

class Derived1 : public Base 
{ 
public: 
    template<typename... T> 
    explicit Derived1(T&&... t) : Base(std::forward<T>(t)...) { 
     std::cout << "Derived1::init logic goes here" << endl; 
    } 
}; 
+0

@DavidHollman : 예, 아니오. 템플릿 생성자는 결코 복사 또는 이동 생성자가 아니므로 값에 의한 전달은 템플릿을 사용하지 않습니다. 그러나 생성자를 직접 호출하면 원하지 않는 생성자를 얻을 수 있습니다. http://akrzemi1.wordpress.com/2013/10/10/too-perfect-forwarding/ –

+0

(코멘트를 이해할 수 있도록 재 게시)를 참조하십시오. 기본 복사 및 생성자 오버로드에 과부하가 걸리지 않습니까? –

1

또 다른 방법은 '이라는 객체 생성 후 init()를 호출하는 클래스, 특별 공장 확인 '생성자 :

#include <iostream> 

class Base 
{ 
    public: 
    template <typename Derived> 
    static Derived construct() { 
     Derived derived; 
     derived.hello(); 
     return derived; 
    } 

    protected: 
    Base() {}; 

    public: 
    virtual ~Base() {}; 

    public: 
    virtual void hello() = 0; 
}; 

class Derived : public Base 
{ 
    public: 
    virtual void hello() { 
     std::cout << "Hello\n"; 
    } 
}; 

int main() 
{ 
    Derived d = Base::construct<Derived>(); 
}