2011-11-08 33 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號線的解決方案」。

最壞的解決方案是該參數存儲在一個全局變量,由於您使用C++,靜態變量的析構函數也可以作爲一個atexit處理器在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"); 
} 

示範:http://www.ideone.com/bfYnY

需要注意的是靜態變量綁定到他們的名字,所以你不能說

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

來調用atexit所有內容。但是,你可以把靜態變量本身採取一系列

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

最後,地道的C++,我不認爲你需要使用這些技巧......你可以存儲的類型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,但它做任何事都應 可以不帶參數(包括boost::function)被稱爲工作。 或者你可以編寫自己的類,從CallInDestructor得到,只要你採取措施確保所有實例都是動態分配的(因爲構造函數註冊了對象,所以它將被刪除)。這些類可以包含所需的任何其他數據。

+0

它似乎非常有用。爲什麼是傳統? :-) – Mikhail

+1

@Misha因爲你不能傳遞它的參數,並且因爲你不需要它在C++中;只需定義一個靜態變量,它的析構函數可以做任何你想要的。 –