2011-11-21 2 views
4

RAII 관용구가 클래스에서 필요로하는 리소스에 적용될 때 이해합니다. (틀린 경우 수정하십시오), 리소스가 필요한 클래스는 적절한 유형의 멤버를 정의해야하며 해당 소멸자는 사용하여 클래스의 인스턴스가 파괴 될 때 다음과 같이 자동으로 호출 :RAII를 확장 초기화가 필요한 클래스 멤버에 어떻게 적용 할 수 있습니까?

외에도 힙에 리소스를 할당하는 스마트 포인터를 사용에서
class Skybox 
{ 
    public: 
     Skybox() : tex_(...) {} 

    private: 
     Texture tex_; 
}; 

는이 패턴을 적용 할 수있는 방법을 자원 구성원이 실행해야 할 몇 가지 코드를 요구하는 경우 Skybox 생성자에서 리소스를 초기화하기 전에? 예를 들어 :

class Skybox 
{ 
    public: 
     Skybox(const std::string& fileName); 

    private: 
     Texture tex_; 
} 

Skybox::Skybox(const std::string& fileName) 
{ 
    // read stuff from skybox initialization file 
    // including various texture parameters such as texture file 
    ... 
    // initialize tex_ based on information read above 
} 

이 업데이트 : Texture 클래스가 생성자에서 수행되는 모든 초기화가 필요

+0

'Texture' 클래스는'tex_.init (...) '처럼 나중에 초기화 할 수 있습니까? –

+0

아니요, 그렇지 않습니다. 나는 질문 문안을 갱신 할 것이다. –

+0

tex를 초기화하는 것 이외의 다른 용도로 사용할 필요가있는 사전 계산이 있습니까? 그렇지 않다면, 파일 이름을 취하고 모든 처리를 자체 초기화의 일부로 수행하는 질감 생성자를 생성하십시오. – matthias

답변

10

랩 함수에 초기화 코드 (예 : 더 Texture::Init() 방법은 사용할 수 없습니다), 그 기능 (멤버를 사용 또는 비 멤버 (정적 또는 비 정적)을 사용하여 멤버 변수를 초기화합니다.

Texture Skybox::init_tex(std::string const& fileName) { 
    // read stuff from file, including textureFile 
    // initialize result 
    return Texture(...); 
} 

Skybox::Skybox(std::string const& fileName): 
    tex_(init_tex(fileName)) 
{ } 

초기화 함수는 정적 함수 여야합니다. 아직 초기화되지 않은 멤버를 사용하지 않도록주의하십시오. 아직 초기화되지 않은 Skybox 인스턴스에서 init_tex을 호출해야합니다. C++ 11 기능 (가변 인자 템플릿과 완벽한 포워딩)를 사용

+3

니스.정적 함수가 안전할까요? –

+4

생성자에서 비 정적 멤버 함수를 사용하려면 많은주의와 비 로컬 보장이 필요합니다. 정적 멤버 함수는 모든 걱정을 제거합니다. –

+1

람다! –

0

이 템플릿 생성자에 감사를 달성 할 수있다 :

#include <utility> 
template<class T> 
class raii_wrapper 
{ 
    public: 

template<typename... Arg> 
    raii_wrapper(Arg&&... args) : obj(std::forward<Arg>(args)...) {} 

    private: 
     T obj; 
}; 

struct foo 
{ 
    foo(){} 
}; 

struct foo_1 
{ 
    foo_1(int){} 
}; 

struct foo_2 
{ 
    foo_2(int,int&){} 
}; 

int main() 
{ 
    raii_wrapper<foo> f; 
    raii_wrapper<foo_1> f1(1); 
    int i(3); 
    raii_wrapper<foo_2> f2(1,i); 
    return 0; 
} 

C++ 03/98, 템플릿 생성자에서은 (여전히 솔루션입니다 boost는 variadic template와 argument passing을 돕는다.) make_share_ptr과 같은 기능 구현을 참조하십시오.

+0

나는 이것이 도움이된다고 생각하지 않는다. –

+1

예제에서 'Skybox' 및'Texture' 클래스와 직접적으로 관련되도록 코드를 변경하십시오. –

2

아마도 파일의 읽기가 Skybox와 관련이 없어 어딘지 다른 곳에서 유용 할 수 있으므로 텍스처 생성을 자유 함수로 캡슐화해야 할 것입니다. 나는 다른 이름이 Factory이라고 생각합니다.

Tex tex_from_file(const std::string&) { 
    // ... 
} 

class Skybox { 
    Skybox(const std::string& s) : tex_(tex_from_file(s)) {} 
}; 

도 좋네요은 Tex 개체에서 스카이 박스 작도 할 것이다. 그러나 이렇게하려면 Tex이 복사 가능하거나 구성 가능해야합니다. 이 경우 적절한 해결 방법은 std::unique_ptr<Tex> 반환 할 수 있습니다.

0

Texture 클래스에 기본 생성자가 있고 스와핑을 지원하는 경우 로컬 변수로 리소스를 초기화하고 생성자 끝에 스왑 할 수 있습니다.

Skybox::Skybox(const std::string& fileName) 
{ 
    Texture localTex(fileName); 
    //... 
    tex_.swap(localTex); 
}