当对象超出范围时执行一些代码

时间:2017-01-17 20:24:20

标签: c++ c++11

有些时候我想确保在从其他函数返回之前执行某些函数调用,或者减少整数。

例如,请考虑以下代码:

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

我想确保myvariable总是递减,如果有异常则没有materiable,或者返回调用。 在C ++中是否有任何构建对象,或者我应该创建自己的类来接受std :: function并在对象析构函数超出范围时执行它?

例如,在C#中有try..catch ... finally块,最后你可以在从函数返回之前放入你想要执行的任何代码。

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

您可以这样做:

   var results = (from drECO in dtECO.AsEnumerable() 
                    join drBOMTo8 in dtBOM.AsEnumerable() on drECO.Field<string>("PN8Dig") equals drBOMTo8.Field<string>("PN8Dig")

                     from drBOMFrom8 in dtBOM.AsEnumerable ()
                     join drFAA8 in dtFAA.AsEnumerable () on drBOMFrom8.Field<string>("PN8Dig") equals drFAA8.Field <string>("PN8Dig")

                     from drBOMFromMon in dtBOM .AsEnumerable ()
                     join drFAAMon in dtFAA .AsEnumerable () on drBOMFromMon.Field <string>("Mon") equals drFAAMon.Field <string>("Mon")


                      select new
                     {
                         PN = drECO .Field <string>("PN"),
                         PNNEWREV = drECO.Field <string>("PNNewRev"),
                         PN8DIG = drECO.Field <string >("PN8Dig"),
                         ECO = drECO .Field <string >("ECO"),
                         MON = drFAAMon.Field <string>("Mon"),
                         SUPNUM = drFAAMon.Field <string>("SupNum"),
                         URL = drFAAMon.Field <string>("URL")
                     }).Distinct ();

Live Example

或更像您的情景:

#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 2

答案 2 :(得分:1)

我经常使用std::unique_ptr,使用lambda作为自定义删除器。这有点尴尬,因为你必须为删除类型做decltype(),但除此之外,它可以节省你写一个10班的课程。

答案 3 :(得分:0)

你必须在一个析构函数中编写一个调用函数或使用lambda等的类。

这是一个名为OnLeavingScope的人。

答案 4 :(得分: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!