|
|
The Curiously Recurring Template Pattern |
|
|
作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站 |
看到这个题目你可能会觉得奇怪,CRTP是什么呢?CRTP是The Curiously Recurring Template Pattern的缩写.
我们先来看一个简单的例子: template <typename Derived> class CuriousBase { … };
class Curious : public CuriousBase<Curious> { … };//摘自<<C++ Templates: The Complete Guide>> //16.3 The Curiously Recurring Template Pattern (CRTP)
如果是第一次看到,你可能会觉得奇怪(我也想了半天),这里不会形成递归吗?这里有两个地方可能会产生递归,首先是声明,其次是实现的时候.比如说下面的代码: template <typename Derived> class CuriousBase { public: CuriousBase() { new Derived; } };
class Curious : public CuriousBase<Curious> { public: Curious() { } }; 如果你的程序中加入了这样的代码,恭喜你了,你中了我们的大奖--崩溃;
你可能会问,即使我们能避免这样的递归,可是这样的结构有什么用呢?
我们先假设有种情况,比如说你的项目里面可能有10000多个类,现在要求你每个类都要实现print()函数,负责将类型的大小输出到std::cout上面,你们的老板还发话了,用函数实现,因为将来这个操作可能需要变更,最可气的是他规定说最好是不要用全局函数.
第一个念头是继承一个有函数print()的接口 class IAblePrint { public: void print() { cout<<sizeof(*this)<<endl; } }; 可惜这样做的结果不是我们需要的,那么我们设这个函数成为虚函数,然后每个类实现自己的?老天,那里有10000多个类等着我们呢.虽然全局函数是个不错的解决方案,但是那个可恶的老板!
直觉告诉我们,这些成员函数一定是要实现的,可是有没有办法让编译器来替我们完成这些无聊的工作呢?
下面就该CRTP登场了 template<typename T> class AblePrintSize { public: void print() { cout<<sizeof(T)<<endl; } };
class Test1:public AblePrintSize<Test1> { int t; };
class Test2:public AblePrintSize<Test2> { int t[2]; };
int main() { Test1 hu1; Test2 hu2;
hu1.print(); hu2.print(); }
这里我们只是自己多写了一个template class就达到了我们的目标.上面的例子可能举的不是很好,下面有个比较好的例子(摘自<<C++ Templates: The Complete Guide>> ),大家可以参考参考
#include <stddef.h>
template <typename CountedType> class ObjectCounter { private: static size_t count; // number of existing objects
protected: // default constructor ObjectCounter() { ++ObjectCounter<CountedType>::count; }
// copy constructor ObjectCounter (ObjectCounter<CountedType> const&) { ++ObjectCounter<CountedType>::count; }
// destructor ~ObjectCounter() { --ObjectCounter<CountedType>::count; }
public: // return number of existing objects: static size_t live() { return ObjectCounter<CountedType>::count; } };
// initialize counter with zero template <typename CountedType> size_t ObjectCounter<CountedType>::count = 0;
/*If we want to count the number of live (that is, not yet destroyed) objects for a certain class type, it suffices to derive the class from the ObjectCounter template. For example, we can define and use a counted string class along the following lines:*/
// inherit/testcounter.cpp
#include "objectcounter.hpp" #include <iostream>
template <typename CharT> class MyString : public ObjectCounter<MyString<CharT> > { … };
int main() { MyString<char> s1, s2; MyString<wchar_t> ws; std::cout << "number of MyString<char>: " << MyString<char>::live() << std::endl; std::cout << "number of MyString<wchar_t>: " << ws.live() << std::endl; }

|
|
相关文章:相关软件: |
|