1、编写可以计数的类:
//.h
class Widget {
public:
Widget() { ++count; }
Widget(const Widget&) { ++count; }
~Widget() { --count; }
static size_t howMany()
{ return count; }
private:
static size_t count;
};
//.cpp
size_t Widget::count = 0;
给多个类编写时繁杂,因此最好能够将“计数过程”打包。
2、物件计数类:
//.h
class Counter {
public:
Counter() { ++count; }
Counter(const Counter&) { ++count; }
~Counter() { --count; }
static size_t howMany()
{ return count; }
private:
static size_t count;
};
//.cpp
size_t Counter::count = 0;
使用方法:A:用作基类;B:用作类成员变量。
目前存在的问题:Counter
中的静态变量 count
属于类,只有一个,但我们需要为每一个使用 Counter 的 class 准备一个。举个例子,如果我们打算对 class1和 class2类对象计数,我们需要两个 static size_t objects,而不是一个。
3、解决办法:把 Counter 变成一个 template:
让每一个想要使用 Counter 的 class,以自己为 template参数具现出这个template类。
//1.h
template<typename T> //此部分代码为关键
class Counter {
public:
Counter() { ++count; }
Counter(const Counter&) { ++count; }
~Counter() { --count; }
static size_t howMany()
{ return count; }
private:
static size_t count;
};
template<typename T> size_t Counter<T>::count = 0; // 模板内容放在.h文件中
3.1、模板Counter的使用方式1:基类公有继承:
class Widget: public Counter<Widget> {
.....
};
//.cpp
Counter<Widget> * ptr1 = new Widget;
delete ptr1; //结果未定义,派生类没释放
存在问题:作为基类,Counter需要虚析构函数,使得效率变低。
3.2、模板Counter的使用方式2:成员变量:
//.h
class Widget {
public:
.....
static size_t howMany()
{return Counter<Widget>::howMany();}
private:
.....
Counter<Widget> c;
};
存在问题:添加成员变量,类对象内存变大。
3.3、模板Counter的使用方式3:基类私有继承:
class Widget: private Counter<Widget> {
public:
// 让 howMany 成为 public,用于访问现有个数
using Counter<Widget>::howMany;
.....
};
//.cpp
Counter<Widget> *pw = new Widget; // 错误! 没有隐式转换函式(implicit conversion)
// 可以将 Widget* 转为 Counter<Widget>*
优势:私有继承禁止了基类指针指向派生类用法;同时派生类对象内存大小不变。
总结:
1、把 Counter 变成一个 template,让每一个想要使用 Counter 的 class,以自己为 template参数具现出这个template类。
2、==推荐使用私有继承(最好)==或集合方式(次之)使用计数模板。