2013-03-06 84 views
1

比方說,我有一個名爲foo的對象的列表。我如何確保在創建第一個foo時調用成員init(),但只調用一次。另外我如何確保何時最後一個對象被銷燬,成員quit()被調用但只有一次。如何確保一個成員函數被調用一次

我知道C++ 11有標準:: call_once的和C++ 03升壓擁有的boost :: call_once的。

我第一次嘗試看起來是這樣,但退出的部分顯然是錯誤的:

class foo 
{ 
public: 

    foo() { init(); } 

    ~foo() 
    { 
     // this is wrong 
     quit(); 
    } 

private: 

    void init() 
    { 
     static boost::once_flag flag = BOOST_ONCE_INIT; 
     boost::call_once(flag, []() { /* init something */ } ); 
    } 

    void quit() 
    { 
     static boost::once_flag flag = BOOST_ONCE_INIT; 
     boost::call_once(flag, []() { /* quit something */ }); 
    } 
}; 

有沒有辦法讓它這是正確的只是依靠C++的設施?

這裏加入少量的什麼,我其實是想這樣做。我試圖在C++類中包裝一個SDL窗口,並且想調用SDL_Init()和SDL_Quit以及適當的時間。 我的第一次嘗試是在這裏:http://pastebin.com/Y9X0UwUB

+1

'call_once'是多個線程試圖調用一個功能,只有其中一人在呼喚它實際上成功。 – 2013-03-06 22:52:40

+0

你可以擴展一下'init()'和'foo'代表什麼?對此有同樣可行的解決方案,但建模的最佳方式取決於您的情況。 – GManNickG 2013-03-06 23:00:42

+0

@sftrabbit - 'call_once'也適用於單線程應用程序。儘管如此,可能會有更多的開銷。 – 2013-03-06 23:07:55

回答

3

這聽起來像你想這些方法是static,然後還要保持住對象的數量,這是遞增/遞減,並檢查在構造函數中的一個私有靜態計數(S )和析構函數。

顯然,如果這是一個多線程的應用程序,你需要某種形式的同步。

+0

爲什麼要靜態靜態方法有幫助?是不是once_flag足夠了? – chhenning 2013-03-06 22:54:26

+0

@chhenning:我想這並不重要初始化是否/退出方法是靜態的,但他們聽起來像他們需要執行不與任何特定的類的實例相關聯的動作,所以這將是有意義的聲明它們的靜態(爲了證明意圖)。 – 2013-03-06 22:55:33

0

您可以創建一個呼籲建設和毀滅的退出函數初始化函數一個新的類,然後讓你的類的所有實例收到一個shared_ptr來在建設這個類的一個實例。

class foo_init_quit { 
    public: 
     foo_init_quit(){init();} 
     ~foo_init_quit(){quit();} 
}; 

std::vector<foo> do_something() { 
    auto init_quit = make_shared<foo_init_quit>(); 
    std::vector<foo> vec; 
    vec.emplace_back(init_quit); 
    //... 
    return vec; 
} 
+0

我正在考慮這些方面。可能是調用quit()的好方法,但是init()不起作用,因爲shared_ptr應該不會被初始化。那裏仍然需要一些東西。我認爲這裏可能有一個有趣的黑客攻擊。 – 2013-03-06 22:50:54

+0

@CrazyEddie嗯,他沒有說init函數應該做什麼,所以我認爲它不需要foo的實例來工作。 – Cubic 2013-03-06 22:52:45

+0

@Cubic:你能否提供一個工作代碼片段。我不能讓你的代碼編譯。謝謝! – chhenning 2013-03-06 23:10:02

0
struct Funkay 
{ 
    Funkay() : { ++count; init(); } 
    ~Funkay() { --count; quit(); } 

private: 
    static size_t count; 
    void init() { if (count == 1) ???; } 
    void quit() { if (count == 0) ???; } 
}; 
size_t Funkay::count = 0; 
+2

如果這個類是可複製的/可移動的,那麼可能會有比遞增更多的遞減。 – ildjarn 2013-03-06 23:15:55

相關問題