在C++中计算物件个数(Objects Counting in C++)

来源:互联网 发布:删除mysql注册表 编辑:程序博客网 时间:2024/05/22 10:31

原文出自:More Effective C++ 电子版 p.452

仅为个人学习,暴露缺点;所以仅供参考,欢迎讨论!

 

需求:当我需要实时了解当前有多少类型的对象同时存在。

设计:比如一开始会这样设计

class Widget {
public:
Widget() { ++count; }
Widget(const Widget&) { ++count; }
~Widget() { --count; }
static size_t howMany() { return count; }

private:
static size_t count;
};

直接在类中增加一个static member data。然后当Widget类型有对象被构造(复制构造)时计数器+1,析构时计数器-1;如果目标仅仅是针对Widget类的话,我们的需求已经被达到了。
但是,当我们需要统计不同类型的对象个数时,就需要换一种更为舒服的实现方式了。

设计一个计数类:

class Counter {
public:
Counter() { ++count; }
Counter(const Counter&) { ++count; }
~Counter() { --count; }
static size_t howMany()
{ return count; }
private:
static size_t count;
};

// 在需要计数的 class 中内嵌一个Counter object。
class Widget {
public:
..... // Widget 该有的所有public 成员,
// 都放在这里。
static size_t howMany()
{ return Counter::howMany(); }
private:
..... // Widget 该有的所有private 成员,
// 都放在这里。
Counter c;
};

// 另一个方法是把Counter 当做base class,像这样:
// 让需要计数的class 继承自Counter
class Widget: public Counter {
..... // Widget 该有的所有public 成员,
// 都放在这里。
private:
..... // Widget 该有的所有private 成员,
// 都放在这里。
};

但是这样设计的话又会出现一个问题,看出来了么?
对,就是static的count。如果我们同时存在A类和B类需要计数,那我们则需要2个static size_t count,而不是一个!

运用C++ 中最广为人知但名称十分诡异的一个技俩:

template <class T>
class Counter {
public:
Counter() { ++count; }
Counter(const Counter& rhs){ ++count; }
virtual ~Counter() { --count; }
static size_t hMany() { return count; }
private:
static size_t count;
};

template <class T>
size_t Counter<T>::count = 0;

现在,Counter 成了一个 template,不论内嵌式设计或继承式 设计,都可以运作了。
class Widget : private Counter<Widget>
{
public:
using Counter<Widget>::hMany;
static size_t getCount() { return Counter<Widget>::hMany(); }
};
class AnotherWidget : public Counter<AnotherWidget>
{
public:
static size_t getCount() { return Counter<AnotherWidget>::hMany(); }
};


int main()
{
cout << sizeof(Widget) << endl;
cout << sizeof(AnotherWidget) << endl;

Widget a,b,c,d,e,f;
cout << f.getCount()<< endl;
AnotherWidget x,y,z;
x=z;
AnotherWidget h = z;
cout<< z.getCount()<<endl;
return 0;
}