其他语言

本类阅读TOP10

·基于Solaris 开发环境的整体构思
·使用AutoMake轻松生成Makefile
·BCB数据库图像保存技术
·GNU中的Makefile
·射频芯片nRF401天线设计的分析
·iframe 的自适应高度
·BCB之Socket通信
·软件企业如何实施CMM
·入门系列--OpenGL最简单的入门
·WIN95中日志钩子(JournalRecord Hook)的使用

分类导航
VC语言Delphi
VB语言ASP
PerlJava
Script数据库
其他语言游戏开发
文件格式网站制作
软件工程.NET开发
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; 




相关文章

相关软件