计算调用函数的次数

时间:2017-10-12 15:47:06

标签: c++

我想计算调用一个函数的次数,这样如果多次调用它,会向开发人员通知一些错误(通过日志记录或断言等)。我希望这个代码能够很好地定义和隔离,以便它可以轻松地在许多函数和成员函数中移植。有点简单:

void function( )
{
    if( is_called_more_than_once( ) )
    {
        // do something to handle the error
    } 
}

void AClass::method( )
{
    if( is_called_more_than_once( ) )
    {
        // do something to handle the error
    } 
}

是否有可能在C ++中,因为它没有反射,以某种方式实现类似的东西?

3 个答案:

答案 0 :(得分:3)

对于独立函数或静态类方法,您可以使用静态局部变量:

void function()
{
    static int num_called = 0;
    if( ++num_called > 1 )
    {
        // do something to handle the error
    }
    ...
}

对于非静态类方法,请为每个方法使用类数据成员,允许类的各个实例进行自己的跟踪:

class AClass
{
private:
    int num_method1_called;
    int num_method2_called;

public:
    AClass();

    void method1();
    void method2();

    ... 
};

AClass::AClass() :
    num_method1_called(0),
    num_method2_called(0)
{
}

void AClass::method1()
{
    if( ++num_method1_called > 1 )
    {
        // do something to handle the error
    }
    ...
}

void AClass::method2()
{
    if( ++num_method2_called > 1 )
    {
        // do something to handle the error
    }
    ...
}

如果错误处理始终相同,请考虑将其解压缩为可重用的帮助程序:

struct callTracker
{
    int counter;
    callTracker() : counter(0) {} 
    void called()
    {
        if( ++counter > 1 )
        {
            // do something to handle the error
        }
    }
};

void function( )
{
    static callTracker tracker;
    tracker.called();
    ...
}

class AClass
{
private:
    callTracker method1_tracker;
    callTracker method2_tracker;

public:
    void method1();
    void method2();

    ... 
};

void AClass::method1()
{
    method1_tracker.called();
    ... 
}

void AClass::method2()
{
    method2_tracker.called();
    ... 
}

可替换地:

struct singleCallTracker
{
    int counter;
    singleCallTracker() : counter(0) {}
    void called()
    {
        if( ++counter > 1 )
        {
            // do something to handle the error
        }
    }
};

struct multiCallTracker
{
    std::map<std::string, singleCallTracker> trackers;
    void called(const std::string &name)
    {
        trackers[name].called();
    }
};

void function()
{
    static singleCallTracker tracker;
    tracker.called();
    ... 
}

class AClass
{
private:
    multiCallTracker method_tracker;

public:
    void method1();
    void method2();

    ... 
};

void AClass::method1()
{
    method_tracker.called(__FUNC__);
    ...
}

void AClass::method2()
{
    method_tracker.called(__FUNC__);
    ...
}

答案 1 :(得分:1)

反射是不必要的,因为调用者称为编译时。 C ++ 11有一个内置的__func__,它被评估为一个普通的C字符串,它是该函数的简单名称。还有typeid(*this).name()来获取*this后面的类的错位名称。

因此,定义一个维护一组字符串的类,并且只有一个方法announce_call。在您定义的每个类中放置该类的实例,可能通过从具有protected实例的人继承。

调用announce_call提供函数名称和类名称。如果函数名称已在集合中,请使用它和类名称记录错误。否则将其添加到集合中。

如果需要,为不属于类的函数提供全局实例。

因此,每类净语法成本是:添加额外的基类,在每个计数函数的开头添加额外的行。

继承提供了主要警告:由于this始终指向函数所属事物的实例,如果B继承自AC拥有实例B但是从A调用两次方法,日志会显示对A的双重调用,而不是B

答案 2 :(得分:0)

我认为这与使用单个宏一样接近:

#define if_called_more_than_once() \
    static int s_nTimesCalled = 0; if (++s_nTimesCalled > 1)

void function( )
{
    if_called_more_than_once()
    {
        // do something to handle the error
    } 
}