静的メンバー変数を使用するのが方法です。ただし、コンパイラは「整数のコピーを作成して最小値に初期化」しません。.ccファイルでそれぞれの定義を提供し、そこで0に初期化する必要があります。(C ++ 11を使用している場合は少し異なりますが、基本的な考え方は同じです。)
静的メンバーの代わりに静的グローバル変数を使用する理由はありません。
foo.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__]など、少し凝ったものなので、各関数でまったく同じ行を使用できます。このような:
foo.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などに依存してください。