奇特递归模板模式

来源:互联网 发布:网络给人们带来的好处 编辑:程序博客网 时间:2024/05/05 12:02

 有些时候需要对一个类新添加的对象进行计数,这个估计很多人都会,所有工作就是添加静态成员、修改构造函数和析构函数而已。但有时候又会有一些麻烦的事发生,就是想对一个类家族的每一个类都进行单独计数时,难道每个类单独添加这样的工作么,这样的工作量也未免太大了吧?但是采用从基类继承下来的方法又会有另一个问题出现,下面看看代码:

01 //: C05:CountedClass2.cpp
02 // Erroneous attempt to count objects.
03 #include <iostream>
04 using namespace std;
05 class Counted {
06 static int count;
07 public:
08 Counted() { ++count; }
09 Counted(const Counted&) { ++count; }
10 ~Counted() { --count; }
11 static int getCount() { return count; }
12 };
13 int Counted::count = 0;
14 class CountedClass : public Counted {};
15 class CountedClass2 : public Counted {};
16 int main() {
17 CountedClass a;
18 cout << CountedClass::getCount() << endl;    // 1
19 CountedClass b;
20 cout << CountedClass::getCount() << endl;    // 2
21 CountedClass2 c;
22 cout << CountedClass2::getCount() << endl;   // 3 (Error)
23 } ///:~

这种情况下是为派生自Counted所有类进行计数,而不是我们要的对每个派生自Counted单独进行计数,因为派生自Counted的所有类都共享了相同且唯一的静态数据成员。这时要怎么办,难道要自己为每个类都进行重复的工作么?其实一种奇特的模板构造实现了这种方式,如下:

 
01 //: C05:CountedClass3.cpp
02 #include <iostream>
03 using namespace std;
04 template<class T> class Counted {
05 static int count;
06 public:
07 Counted() { ++count; }
08 Counted(const Counted<T>&) { ++count; }
09 ~Counted() { --count; }
10 static int getCount() { return count; }
11 };
12 template<class T> int Counted<T>::count = 0;
13 // Curious class definitions
14 class CountedClass : public Counted<CountedClass> {};
15 class CountedClass2 : public Counted<CountedClass2> {};
16 int main() {
17 CountedClass a;
18 cout << CountedClass::getCount() << endl;    // 1
19 CountedClass b;
20 cout << CountedClass::getCount() << endl;    // 2
21 CountedClass2 c;
22 cout << CountedClass2::getCount() << endl;   // 1 (!)
23 
24 } ///:~
 
这样的话每个类都派生于一个唯一的基类,这个基类将它本身(派生类)作为模板参数!它看起来似乎是很奇怪的用法,好像陷入了一个递归的定义。其实由于Counted的数据成员不依赖于类型T,当模板被解析的时候,Counted的大小就可以知道了(这个可以试下用不同的类型参数来实例化Counted,会发现Counted的大小总是相同的)。因此实际上用什么样的参数来实例化Countd无关紧要,因为它的大小总是相同的。当它被解析时,用任意一个Counted实例的派生类当然也就可以了。现在因为每个类都派生自唯一的基类,所以都有属于自己的静态数据,这样就可以对每个派生类进行单独的计数了,而避免了重复的添加工作。