2011-11-08 2 views
3

일련의 정리 기능을 필요에 따라 푸시하고 싶습니다. 필자는 atexit을 사용하여 매개 변수없이 하나의 정리 기능을 수행했지만이 방법을 하나 이상의 정리 기능으로 확장하는 방법을 모르겠습니다. boost :: bind에 익숙하지는 않지만 스레드에 내 함수를 바인드하는 방법은 좋은 생각이라고 가정합니다 ...atexit에 값 전달하기

C++에서는 다음을 얻으려고합니다.

기능 정의

static void closeAnimation(string prefix="");// static member of fileWriter 

코드 :

atexit(boost::bind(fileWriter::closeAnimation, "0")); // I want to first prefix to be "0" 

오류 :

cannot convert ‘boost::_bi::bind_t<void, void (*)(std::basic_string<char>), boost::_bi::list1<boost::_bi::value<const char*> > >’ to ‘void (*)()’ for argument 

미리 감사드립니다.

답변

2

에는 "코드를 복잡하게하지 않고 1 개 라인 솔루션"이 없습니다.

최악의 솔루션은 글로벌 변수에 해당 매개 변수를 저장, 당신은 또한 atexit 핸들러 역할을 수 ++ 정적 변수의 소멸자 C를 사용하고 있기 때문에 위해서는 atexit 핸들러

에서 그것을 검색하는 것입니다. 그런 다음 매개 변수화를 위해 해당 정적 변수의 생성자에서 매개 변수를 전달할 수 있습니다 (예 :

struct AtExitAnimationCloser 
{ 
    const char* _which_param; 

    AtExitAnimationCloser(const char* which_param) : _which_param(which_param) {} 
    ~AtExitAnimationCloser() { FileWriter::closeAnimation(_which_param); } 
}; 

void f() 
{ 
    printf("entering f\n"); 

    static AtExitAnimationCloser s0 ("0"); // registers closeAnimation("0") at exit 
    static AtExitAnimationCloser s1 ("1"); // registers closeAnimation("0") at exit 

    printf("leaving f\n"); 
} 

데모 : 정적 변수는 이름에 바인딩, 그래서 당신은

for (it = vecs.begin(); it != vecs.end(); ++ it) 
{ 
    static AtExitAnimationCloser s (*it); 
} 

모든 콘텐츠를 atexit 전화를 말할 수 http://www.ideone.com/bfYnY

참고. 그러나 당신이 정적 변수 자체가 관용적 C와 함께, 마지막으로 전체 범위

static AnotherAtExitAnimationCloser s (vecs.begin(), vecs.end()) 

을 만들 수 ++ 난 당신이 ... 당신은 타입 T의 벡터를 저장할 수 이러한 트릭을 사용할 필요가 있다고 생각하지 않는 파괴에 ~ T는 fileWriter::closeAnimation로 전화합니다.

+0

참고 : 범위를 저장할 때, 범위를 사용해야하는 경우 컬렉션의 유효 기간을 확인하십시오. –

0

문제는 bind가 함수 객체를 반환하고 atexit이 void를 반환하고 매개 변수를 사용하지 않는 함수에 대한 포인터를 사용한다는 것입니다.

이 작업을 시도 할 수 있습니다 :

void fun() { 
    fileWriter::closeAnimation("0"); 
} 

atexit(fun); 
+0

문자열에 해당하는 값으로 가득 찬 벡터가있는 것과 같은 몇 가지 해결 방법이 있다고 가정하지만 코드를 더 복잡하게하지 않고 한 줄로 처리하려고합니다. – Mikhail

3

atexit은 레거시 C 함수이며 C++에는별로 적합하지 않습니다. 두 개 이상의 함수를 atexit과 함께 등록 할 수 있지만 모두 void (*)()이어야하며 아니요 인수가없는 boost::function이어야합니다.

C++에서 정적 오브젝트의 소멸자가 대부분 atexit의 기능을 모두 포함하지는 않았지만 을 포함합니다.

#include <vector> 

class CallInDestructor 
{ 
    class Registry 
    { 
     std::vector<CallInDestructor*> myInstances; 
    public: 
     register_caller(CallInDestructor* caller) 
     { 
      myInstances.push_back(caller); 
     } 
     ~Registry() 
     { 
      while (!myInstances.empty()) { 
       delete myInstances.back(); 
       myInstances.pop_back(); 
      } 
     } 
    }; 
    static Registry& registry() 
    { 
     static Registry theOneAndOnly; 
     return theOneAndOnly; 
    } 

protected: 
    CallInDestructor() { registry().register_caller(this); } 

public: 
    virtual ~CallInDestructor() {} 
}; 

template<typename Fnc> void callAtExit(Fnc fnc); 

template<typename Fnc> 
class ConcreteCallInDestructor : public CallInDestructor 
{ 
    Fnc myFnc; 
    ConcreteCallInDestructor(Fnc fnc = Fnc()) : myFnc(fnc) {} 
    virtual ~ConcreteCallInDestructor() { myFnc(); } 

    friend void callAtExit<Fnc>(Fnc fnc); 
}; 

template<typename Fnc> 
void 
callAtExit(Fnc fnc) 
{ 
    new ConcreteCallInDestructor<Fnc>(fnc); 
} 

사용 callAtExit 당신이 atexit 것, 그러나 (A boost::function 포함) 인수없이 호출 할 수있는 모든 을 위해 일한다 등 : 귀하의 경우에는, 내가 좋아하는 뭔가 을 쓸 것입니다. 또는 당신은 당신의 자신의 클래스가 모든 인스턴스가 동적이다 이 (생성자는 객체를 등록 이후는 이 삭제 될 수 있도록)하여 할당하도록 조치를 취할만큼 로, CallInDestructor에서 파생 쓸 수 있습니다; 이러한 클래스에는 원하는 추가 데이터가 포함될 수 있습니다.

+0

그것은 매우 유용하게 보인다. 왜 유산인가? :-) – Mikhail

+1

@Misha 인수를 전달할 수 없기 때문에 C++에서는 필요하지 않기 때문에; 소멸자가 원하는대로 수행하는 정적 변수를 정의하십시오. –

관련 문제