2017-01-17 39 views
3

有些時候我想確保某個函數調用在從其他函數返回之前執行,或者整數遞減。當一個對象超出範圍時執行一些代碼

例如考慮這個代碼:

void doSomething() 
{ 
    try 
    { 
     ..... 
     ..... 
     return; 
     ..... 
     ..... 
     ..... 
     return; 
     ...... 
    } catch (...) 
    } 
    myvariable--; 
} 

我想,以確保MYVARIABLE總是遞減,如果有異常,或者回電話沒有母校。 在C++中是否有任何內建對象,或者我應該創建自己的接受std :: function的類,並在對象超出對象析構函數的範圍時執行它?

例如,在C#中有try..catch ... finally塊,最後可以在函數返回之前放置任何想要執行的代碼。

+0

也許使用Boost.ScopeExit? –

+3

標準中沒有任何內容,但按照您的建議編寫自己的「終極」課並不難。 – molbdnilo

+0

是的,完全像Boost.ScopeExit,但我不想使用任何第三方庫。 –

回答

3

您可以在析構函數中編寫自己的,執行某個操作的類。

class DoAction 
    { 
public: 
    DoAction (std::function<void()> func) : m_func (func) 
     { 
     } 
    ~DoAction() 
     { 
     m_func(); 
     } 

private: 
    std::function<void()> m_func; 
    }; 

,然後創建它的一個對象,以下列方式:

DoAction action([&] {/*Code that you want to be executed upon leaving the scope.*/}); 

Live demo

+0

順便提一句,'()'可以從lambda中移除。 – HolyBlackCat

+0

@HolyBlackCat嗯,我過去很少使用無參數的lambdas,所以我輸入'()'出於習慣。感謝您指出了這一點。 –

0

你必須編寫一個類來調用函數或在其析構函數中使用lambda等。

這裏有一個叫OnLeavingScope

1

你可以做這樣的事情:

#include <iostream> 
template <typename T> 
struct decrementer_raii 
{ 
    T& var; 
    decrementer_raii(T& v) : var(v) {} 
    ~decrementer_raii() { --var; } 
}; 

int main() 
{ 
    int x = 1; 
    { 
     decrementer_raii<int> dec(x); 
    } 
    std::cout << x; // should print 0. 
} 

Live Example

還是更喜歡您的方案:

#include <iostream> 
template <typename T> 
struct decrementer_raii 
{ 
    T& var; 
    decrementer_raii(T& v) : var(v) {} 
    ~decrementer_raii() { --var; } 
}; 

void foo(int& x) 
{ 
    decrementer_raii<int> dec(x); 
    std::cout << x << "\n"; // x is still the original value passed-in (14) 
    for (int i = 0; i < 10; ++i) 
    { 
     if (i == 4) throw 10; // force a throw 
    } 
} 

int main() 
{ 
    int x = 14; 
    try { 
     foo(x); 
    } 
    catch(...) {} 
    std::cout << x; // should print 13. 
} 

Live Example 2

+0

謝謝PaulMcKenzie –

0

你編寫一個簡單的包裝類的建議解決方法應該工作得很好。據我所知,在C++中沒有「內置」的方法。

我寫了一個名爲Finally的簡單類,它只是做你想做的事情,只要它超出範圍就調用一個存儲函數。

#include <functional> 
#include <iostream> 
#include <stdexcept> 

class Finally 
{ 
public: 
    explicit Finally(std::function<void()> func); 
    ~Finally(); 
private: 
    std::function<void()> func; 
}; 

Finally::Finally(std::function<void()> func) 
    : func(func) 
{} 

Finally::~Finally() 
{ 
    func(); 
} 

void CallOnException() 
{ 
    std::cout << "Function was called!" << std::endl; 
} 

void Run() 
{ 
    const Finally finally(CallOnException); 

    std::cout << "Throwing exception now!" << std::endl; 
    throw std::runtime_error("Runtime error"); 

    std::cout << "This code will not be run." << std::endl; 
} 

int main() 
{ 
    try 
    { 
     Run(); 
    } 
    catch(...) 
    { 
     /* Handle exceptions */ 
    } 

    return 0; 
} 

這個簡單程序的輸出是:

Throwing exception now! 
Function was called! 
+0

有一種內置的方式,您正在使用 - 它被稱爲析構函數。 –

+0

謝謝JonatanE –

1

我經常使用std::unique_ptr爲此,使用lambda作爲定製刪除。這有些尷尬,因爲您必須爲刪除類型執行decltype(),但除此之外,它可以節省您編寫10班班級的時間。

+2

一個可行的例子將可用 – Slava

相關問題