第一章 基于Policy的Class设计

2018-04-09  本文已影响0人  szn好色仙人
  • 关于技术:目前并没有一成不变即可套用的代码,可以在某种受控情况下将继承而来的类组合起来。仅仅是将被组合的基类结合在一起并建立一组用来访问其成员的简单规则,除非情况极为单纯,否则结果难以让人接受
  • 关于类型信息:基类并没有足够的类型信息来继续完成他们的工作。比如,由一个DeepCopy Class来为其派生类做出深层拷贝,但是DeepCopy并不清楚其派生类的类型
  • 关于状态处理:基类实作之各种行为必须操作相同的数据,这意味着他们必须虚继承一个持有该数据的基类,由于总是user class继承library class,这会使得设计更加复杂且更加没有弹性
  • 无法特化数据成员
  • 成员函数的特化无法"依理扩张":可以对单一模板参数的模板类特化其成员函数,却无法对使用多个模板参数的模板类特例化其个别成员函数
template<typename T>
class CTest
{
public:
  void Fun(){};
};
template<> void CTest<char>::Fun(){}               //编译ok

template<typename T, template U>
class CTest1
{
public:
  void Fun(){};
};
template<typename T> void CTest1<char, T>::Fun(){} //编译报错
  • 程序库设计者不能提供多笔缺省值:只能对每个成员函数提供一份缺省作品,无法对同一个成员函数提供多份缺省作品
//方法一:
template<typename T>
class CNewCreator
{
public:
    static T* Create() { return new T; }
};

//方法二:
template<typename T>
class CMallocCreator
{
public:
    static T* Create()
    {
        void* pBuff = malloc(sizeof(T));
        if (pBuff)
        {
            return new (pBuff) T;   //定位new 需要包含头文件 #include <new>
        }
        return nullptr;
    }
};

//方法三:
template<typename T>
class CCloneCreator
{
public:
    CCloneCreator(T* pTem = nullptr) : pValue(pTem){}

public:
    T* Create()
    {
        return pValue ? pValue->Clone() : nullptr;
    }

    T* Get() { return pValue; }
    void Set(T* pTem) { pValue = pTem;}

private:
    T* pValue;
};

如上,任何一个police都可以有无限份实现方式,实现police的类一般不被单独使用,主要用于继承或内含与其他类中。policies接口和一般的类接口不同,他比较松散,他是语法导向而非标记导向。换句话说,Create明确定义的是"怎样的语法构造其所规范的类"而非"必须实现出哪些函数"。例如Create Policy没有规定Create必须是static还是virtual,他只要求class必须定义出Create()且不接受参数的同时返回指向新对象的指针
接下来设计一个类来利用Create Policy:

template<typename T>
class CTest : public T 
{
public:
    void Create();
};

template<typename T>
void CTest<T>::Create()
{
    T::Create();
}

int _tmain(int argc, _TCHAR* argv[])
{
    CTest<CNewCreator<int>> Test;
    Test.Create();  //调用方法一的Create()

    CTest<CMallocCreator<double>> Test1;
    Test1.Create(); //调用方法二的Create()
    return 0;
}

看以上代码,当Test对象需要产生一个特定类型的对象时,可以让CTest类的使用者自行装配他需要的机能,这便是 policy-based class的设计主旨

//这里的U是模板类T的模板参数无法在CTestInt类中使用,可以省略。
//T则是CTestInt的模板参数
template<template<typename/* U*/> class T>  
class CTestInt : public T<int>
{
public:
    void Create();
};

template<template<typename/* U*/> class T>
void CTestInt<T>::Create()
{
    printf("%s\n", typeid(T).name());   //#include <typeinfo>
    T<int>::Create();
}

int _tmain(int argc, _TCHAR* argv[])
{
    CTestInt<CNewCreator> TestInt;      //此处无需传入CNewCreator的模板参数
    TestInt.Create();   //会调用方法一的Create 输出"class CNewCreator"

    return 0;
}
#include <cassert>
#include <new>

template
<
    typename T,                         //被指对象类型
    template<typename> class CCheck,    //提供Check功能
    template<typename> class CAlloc     //提供分配功能
>
class CSmartPtr : public CCheck<T>, public CAlloc<T>
{
public:
    CSmartPtr() : pValue(nullptr){}

public:
    T* operator->()
    {
        CCheck<T>::Check(pValue);
        return pValue;
    }

    void Init()
    {
        pValue = CAlloc<T>::Create();
    }

private:
    T* pValue;
};


template<typename T>
class CNotCheck
{
public:
    static void Check(T*){}
};

template<typename T>
class CCheck
{
public:
    static void Check(T* pTem)
    {
        if (!pTem)
        {
            assert(false);
        }
    }
};


template<typename T>
class CNewCreator
{
public:
    static T* Create() { return new T; }
};

template<typename T>
class CMallocCreator
{
public:
    static T* Create()
    {
        void* pBuff = malloc(sizeof(T));
        if (pBuff)
        {
            return static_cast<T*>(pBuff);
        }
        return nullptr;
    }
};

template<typename T>
class CNotCreator
{
public:
    static T* Create()
    {
        return nullptr;
    }
};

struct STest
{
    STest() : nValue(4096) { printf("STest\n"); }
    int nValue;
};

int _tmain(int argc, _TCHAR* argv[])
{
    CSmartPtr<STest, CCheck, CNewCreator> pTest;
    pTest.Init();                   //输出"STest"
    auto nTem = pTest->nValue;      //nTem = 4096

    CSmartPtr<STest, CNotCheck, CMallocCreator> pTest1;
    pTest1.Init();                  //并没有输出 因为malloc并不调用构造函数
    auto nTem1 = pTest1->nValue;    //nTem1 = -842150451

    CSmartPtr<STest, CCheck, CNotCreator> pTest2;
    pTest2.Init();
    auto nTem2 = pTest2->nValue;    //引发中断
    return 0;
}
#include <cstdio>
#include <typeinfo>


template<typename T, template<typename> class CCheck>
class CTest : public CCheck<T>
{
public:
    template<typename T1, template<typename> class C1>
    CTest(const CTest<T1, C1>& Test) : CCheck<T>(Test)
    {
        printf("Type Change\n");

        printf("%s, %s\n", typeid(T).name(), typeid(CCheck).name());
        printf("%s, %s\n", typeid(T1).name(), typeid(C1).name());
    }

    CTest(){}
};


template<typename T>
class CCheckMode_0{};


template<typename T>
class CCheckMode_1
{
public:
    CCheckMode_1(const CTest<T, CCheckMode_0>&)
    {
        printf("Deal Change\n");
    }

    template<typename T1>
    CCheckMode_1(const CTest<T1, CCheckMode_0>& TestC)
    {
        printf("Super Change\n");
    }
};


int main()
{
    CTest<int, CCheckMode_0> T0;
    CTest<int, CCheckMode_1> T1(T0);
    printf("------------------\n");
    CTest<double, CCheckMode_1> T2(T0);

    //CTest<int, CCheckMode_0> T3(T1);  //编译报错,没有定义对应的拷贝构造函数

    /*
    输出:
    Deal Change
    Type Change
    int, class CCheckMode_1
    int, class CCheckMode_0
    ------------------
    Super Change
    Type Change
    double, class CCheckMode_1
    int, class CCheckMode_0
    */

    return 0;
}
上一篇下一篇

猜你喜欢

热点阅读