繁体   English   中英

计算一个函数被调用的次数

[英]Counting how many times a function is called

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

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 ++没有反射功能,是否有可能以某种方式实现类似目标?

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

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__);
    ...
}

反射不是必需的,因为调用者称为编译时间。 C ++ 11有一个内置的__func__ ,它的计算结果为纯C字符串,即该函数的未经修饰的名称。 还有typeid(*this).name()来获取*this后面的类的错误名称。

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

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

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

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

继承提供了一个主要警告:因为this总是指向该函数所属的事物的一个实例,如果B继承自AC拥有一个实例B但是从A调用了两次方法,则日志将显示对A的两次调用,而不是比B

我认为这与单个宏所能达到的效果非常接近:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM