C++primer学习:模板编程(2):类模板的定义

类模板是用来生成类的蓝图的,与函数模板不同的是,编译器不能为类模板推导模板参数的类型,我们必须要提供额外的信息.

[1]定义类模板:

####template<typename T> class
{
}

[2]类模板的成员函数本身是一个普通的函数,但是由于类模板的每个实例都有自己的模板参数,因此定义在类模板的成员函数就必须以关键字template开头,后接模板参数.

[3]当我们在类的作用域之内使用类模板类型时可以不(当然也可以提供)提供模板实参.比如 Blob();//构造函数

[4]类模板和友元.类与友元(类或者函数)各自是否是模板是相互无关的,如果一个类模板包含一个非模板友元,则该友元对所有实例都有访问权,如果友元自身是模板,则类可以给所有友元实例授权,也可以只授权给特定实例.//注意:如果只授权给特定的实例,就必须进行前置声明.

[5]类模板的static成员,每个实例拥有各自的static成员,所以在类外定义的时候需要定义成模板.

[练习]:编写自己版本的Blob(StrBlob的模板化),并且重载必须的const成员.
#ifndef CP5_ex16
#define CP5_ex16                                                           
#include "iostream"
#include "fstream"
#include "sstream"
#include "vector"
#include "memory"
#include "initializer_list"
#include "new"
#include "string"
using namespace std;
template<typename T> class BlobPtr;//前置声明
/***********定义类模板Blob****************/
template <typename T>class Blob
{
    friend class BlobPtr<T>;
public:
    /************给类型取别名******************/
    using size_type = typename vector<T>::size_type;
    //构造函数
    Blob() :data(std::make_shared<vector<T>>()) {};//默认初始化
    Blob(initializer_list<T>il) : data(make_shared<vector<T>>(il)){};//列表初始化
    Blob(const Blob & rhs){//拷贝初始化
        data = make_shared<vector<T>>((*rhs.data));
    }
    Blob& operator= (const Blob& rhs)
    {
        data = make_shared<vector<T>>((*rhs.data));
        return *this;
    }
    size_type size()const { return data->size(); };
    bool empty() const { return data->empty(); }
    void push_back(const T & s) { data->push_back(s); };
    void pop_back() { check(0, "pop_back on empty Blob"); data->pop_back(); };
    T& front(){ check(0, "front on empty Blob"); return data->front() };
    T& back(){ "back on empty Blob"; return data->back(); };
    const T& front()const{ check(0, "front on empty Blob"); return data->front(); };
    const T& back()const{ "back on empty Blob"; return data->back(); };
    /*********重载运算符*****************/
    const T& operator[](size_type i)const{//const版本
        check(i, "subscript out of  range");
        return (*data)[i];
    }
    T& operator[](size_type i){//非const版本
        check(i, "subscript out of  range");
        return (*data)[i];
    }

private:
    shared_ptr<vector<T>>data;//智能指针
    void check(size_type, const string&)const;//检查参数的正确性

};
template<typename T>
void Blob<T>::check(size_type i, const string&msg)const
{
    if (i >= data->size())
        throw out_of_range(msg);
}
/***********定义类模板BlobPtr****************/
template <typename T>//前置声明
bool operator ==(const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);

template <typename T>//前置声明
bool operator < (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);
template <typename T>class  BlobPtr
{
    /*******************重载关系运算符:友元声明**********************/
    friend bool operator==<T>
    (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);
    friend bool operator<<T>
        (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs);
public:
    BlobPtr() :curr(0){};
    BlobPtr(Blob<T>& a, size_t sz = 0) :wptr(a.data), curr(sz){};
    bool operator != (const BlobPtr & p){ return p.curr != curr; }

    /*************定义解引用运算符*************/
    T& operator*()const  { 
        auto p = check(curr, "deference past end");
    return (*p)[curr]; 
    }
    /*************定义递增和递减***********************/
    BlobPtr& operator++(){//前置运算符
        check(curr, "the curr past the end");//可递增到[size]
        ++curr;
        return *this;
    }
    BlobPtr& operator--(){//前置运算符
        --curr;
        check(curr, "the curr past the end");//可递增到[size]
        return *this;
    }
    BlobPtr operator++(int ){//后置运算符
        auto ret = *this;
        ++(*this);
        return ret;
    }
    BlobPtr operator--(int){//后置运算符
        auto ret = *this;
        --(*this);
        return ret;
    }
private:
    weak_ptr<vector<T>> wptr;
    size_t curr;//定义下标
    shared_ptr<vector<T>> check(size_t, const string&)const;
};
/***********定义check********************/
template <typename T>
shared_ptr<vector<T>> BlobPtr<T>::check(size_t i, const string& msg)const
{
    auto p = wptr.lock();
    if (!p)//如果所指对象有效
        throw::runtime_error("unbound StrBlobPtr");
    if (i >= p->size())
        throw::out_of_range(msg);
    return p;
}
/*******************定义==**********************/
template <typename T>
bool operator ==(const BlobPtr<T>& lhs, const BlobPtr<T>& rhs)
{
    if (lhs.wptr.lock() != rhs.wptr.lock())
        throw::runtime_error("ptr to different Blob");
    return lhs.curr == rhs.curr;
}
/*******************定义<**********************/
template <typename T>
bool operator < (const BlobPtr<T>& lhs, const BlobPtr<T>& rhs){
    if (lhs.wptr.lock() != rhs.wptr.lock())
        throw::runtime_error("ptr to different Blob");
    return lhs.curr < rhs.curr;

}

#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值