[英]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
繼承自A
而C
擁有一個實例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.