2012-05-28 1 views
2

PIMPL Idiom은 공개 클래스가 공용 클래스가 포함 된 라이브러리 외부에서 볼 수없는 구조 나 클래스를 래핑하는 구현 숨기기 기술입니다. 이렇게하면 라이브러리 사용자의 내부 구현 세부 사항과 데이터가 숨겨집니다.PImpl 대신 불투명 한 참조. 가능한가?

동일한 참조를 사용하여 구현할 수 있습니까?

MCanvasFont.h

namespace Impl { 
    class FontDelegate; 
} 

class MCanvasFont 
{ 
public: 
    MCanvasFont(); 
    virtual ~MCanvasFont(); 

protected: 
    // Reference count 
    long m_cRef; 

    // agg font delegate 
    const Impl::FontDelegate& m_font; 
} 

MCanvasFont.cpp

// helpers 
#include "ImplHelpers/FontDelegate.h" 

MCanvasFont::MCanvasFont() 
: m_cRef(1), 
    m_font(Impl::FontDelegate()) 
{ 
    // constructor's body 
} 

P.S. 이 코드는 G ++에서 문제없이 컴파일됩니다.

답변

5

은 프로그램에 오류가 있습니다, 그것은 생성자의 initialiser 목록입니다 : Impl::FontDelegate()

MCanvasFont::MCanvasFont() 
: m_cRef(1), 
    m_font(Impl::FontDelegate()) // <--- BANG 
{ 

문제는 그것이 일시적으로 오브젝트를 구축한다는 것이다. 이것은 생성자보다 오래 머 무르지 않습니다. 실제로 생성자 본문에 들어가기 전에 실제로 파기됩니다. 수명이 다르게 나타나는 표현의 수명이기 때문입니다. 그러므로 m_font 참증은 순전히 유효하지 않습니다. 당신이 당신이 당신의 런타임에서 활성화 예외가없는 한 그 할당이 실패하면 당신은 정의되지 않은 영역에있어 수동으로 할당 된 객체 (*new Impl::FontDelegate())를 사용하여 초기화 할 수 있지만

. 어쨌든 소멸자의 객체는 여전히 delete이어야합니다. 따라서 참조가 실제로 어떤 이점도 얻지는 못합니다. 단지 약간의 부 자연스러운 코드를 만듭니다. 내가 대신 const를 포인터를 사용하는 것이 좋습니다 :

const Impl::FontDelegate* const m_font; 

편집 : 당신이 이것을 실행하면

#include <iostream> 

struct B 
{ 
    B() { std::cout << "B constructed\n"; } 
    ~B() { std::cout << "B destroyed\n"; } 
}; 

struct A 
{ 
    const B& b; 
    A() : 
     b(B()) 
    { 
     std::cout << "A constructed\n"; 
    } 
    void Foo() 
    { 
     std::cout << "A::Foo()\n"; 
    } 
    ~A() 
    { 
     std::cout << "A destroyed\n"; 
    } 
}; 

int main() 
{ 
    A a; 
    a.Foo(); 
} 

, 출력 될 것입니다 :

그냥 가지고,이 동등한 예를 들어 문제를 설명하기 위해
B constructed 
B destroyed 
A constructed 
A::Foo() 
A destroyed 

따라서 b은 거의 즉시 유효하지 않습니다.

+1

할당이 실패하면 예외가 발생하므로 문제가 없습니다. (예외 생성자 문제를 제외하고) – Hurkyl

+0

개체를 정적으로 할당하기 위해 싱글 톤 패턴을 사용할 수 있습니다. GetInstance는 정적 객체에 대한 참조를 반환합니다. – Steed

+0

임시 수명은 실제로 생성자의 본문을 포함하도록 확장됩니다. 그러나 여러분이 말했듯이, 그것은 대상의 수명을 확실히 커버하지 못합니다. –