使用静态成员变量是要走的路。但是,编译器不会“创建整数的副本并将其初始化为最小值”;您必须为 .cc 文件中的每一个提供一个定义,并在那里将其初始化为 0。(如果您使用的是 C++11,情况会有所不同,但基本思想是相同的。)
没有理由使用静态全局变量而不是静态成员。
富.h:
class Foo {
static int countCtor_;
static int countDtor_;
static int countprint_:
Foo();
~Foo();
static void print();
};
foo.cc:
#include <iostream>
#include "foo.h"
int Foo::countCtor_ = 0;
int Foo::countDtor_ = 0;
int Foo::countprint_ = 0;
Foo::Foo() {
++countCtor_;
// Something here
}
Foo::~Foo() {
++countDtor_;
// Something here
}
void Foo::print() {
++countprint_;
std::cout << "Ctor: " << countCtor_ << "\n"
<< "Dtor: " << countDtor_ << "\n"
<< "print: " << countprint_ << "\n";
}
但是,如果你有很多函数,所涉及的重复有点烦人——当你的意思是 ++countBaz_ 时,很容易意外地执行 ++countBar_ (特别是如果你复制和粘贴样板文件),所以你可能想要一些东西有点花哨,例如静态映射和递增计数[__FUNC__]的宏,因此您可以在每个函数中使用完全相同的行。像这样:
富.h:
#include <map>
class Foo {
static std::map<const char*, int> counts_;
Foo();
~Foo();
void print();
};
foo.cc:
#include <iostream>
#include "foo.h"
std::map<const char *, int> Foo::counts_;
#define INC_COUNT_() do { ++counts_[__FUNC__]; } while (0)
Foo::Foo() {
INC_COUNT_();
// Something here
}
Foo::~Foo() {
INC_COUNT_();
// Something here
}
void Foo::print() {
INC_COUNT_();
for (std::map<const char *, int>::const_iterator it = counts_.begin();
it != counts_.end(); ++it) {
std::cout << it->first << ": " << it->second << "\n";
}
}
在上面的示例代码中,__FUNC__ 是一个占位符。不幸的是,没有可以使用的符合标准的值来代替它。大多数编译器都有一些 __func__、__FUNC__、__FUNCTION__、__FUNCSIG__ 和 __PRETTY_FUNCTION__ 的子集。但是,这些都不是 C++03 中的标准。C++11 确实将 __func__ 标准化,但只是作为“实现定义的字符串”,不能保证它是有用的,甚至是唯一的。最重要的是,不同编译器的值会有所不同。此外,其中一些可能是宏而不是标识符,以使事情变得更有趣。
如果你想要真正可移植的代码,在 C++11 中,你可以使用类似 string(__func__) + ":" + STRINGIZE(__LINE__) 的东西——这有点难看,但至少每个函数都有一个唯一的名称。而在 C++03 中,没有等价物。如果您只需要“足够便携”,请查阅您使用的每个编译器的文档,或者依赖 autoconf 之类的东西。