C++ - 类模板(class template) 详解 及 代码

类模板(class template) 详解 及 代码

 

本文地址: http://blog.csdn.net/caroline_wendy/article/details/16906827

 

类模板(class template)需要添加模板参数(template parameter), 即最前面添加"template <template T>";

把所有需要使用模板类型的位置, 使用"T"代替; 使用时需要填加"Class<T>",指定模板参数;

在定义类的成员函数(member function)时, 也需要添加类的模板参数"template <template T>",

并且在声明函数的归属类时, 类需要转换为模板类, 即"Class::"转换为"Class<T>::";

如果在类中, 如果使用本类对象, 即当前对象, 则可以不添加模板参数(添加也不没有问题);

其余注意初始化列表"initializer_list"的用法, 和前缀++或--与后缀++或--在重载时的区别;

代码如下:

/*
 * cppprimer.cpp
 *
 *  Created on: 2013.11.21
 *      Author: Caroline
 */

/*eclipse cdt, gcc 4.8.1*/

#include <iostream>
#include <vector>
#include <initializer_list>
#include <memory>
#include <cstddef>

template <typename T> class BlobPtr;
template <typename T> class Blob;

/*Blob: Binary Large OBject*/
template <typename T> class Blob {
	friend class BlobPtr<T>;
public:
	typedef T value_type;
	typedef typename std::vector<T>::size_type size_type;
	Blob ();
	Blob (std::initializer_list<T> il); //可以使用初始化列表, {}
	size_type size() const { return data->size(); }
	bool empty() const { return data->empty(); }
	void push_back (const T &t) { data->push_back(t); }
	void push_back (T &&t) { data->push_back(std::move(t)); } //右值操作
	void pop_back ();
	T& back ();
	T& operator[] (size_type i) ;
private:
	std::shared_ptr<std::vector<T> > data;
	void check (size_type i, const std::string &msg) const; //验证给定的索引
};

template <typename T>
Blob<T>::Blob () : data(std::make_shared<std::vector<T>>()) {}

template <typename T>
Blob<T>::Blob (std::initializer_list<T> il) :
        data(std::make_shared< std::vector<T> >(il)) {}

/*验证给定的索引*/
template <typename T>
void Blob<T>::check (size_type i, const std::string &msg) const
{
	if (i >= data->size())
		throw std::out_of_range (msg); //抛出异常
}

template <typename T>
T& Blob<T>::back ()
{
	check (0, "back on empty Blob");
	return data->back ();
}

template <typename T>
T& Blob<T>::operator[] (size_type i)
{
	check (i, "subscript out of range");
	return (*data)[i];
}

template <typename T>
void Blob<T>::pop_back ()
{
	check (0, "pop_back on empty Blob");
	data->pob_back ();
}

template <typename T>
class BlobPtr {
public:
	BlobPtr () : curr (0) {}
	BlobPtr (Blob<T> &a, size_t sz=0) : wptr(a.data), curr (sz) {}
	T& operator* () const {
		auto p = check (curr, "dereference past end");
		return (*p) [curr];
	}
	BlobPtr& operator++ (); //前缀操作符
	BlobPtr& operator-- ();
	BlobPtr operator++ (int); //后缀操作符
	BlobPtr operator-- (int);
private:
	std::shared_ptr<std::vector<T>> check (std::size_t, const std::string&) const;
	std::weak_ptr<std::vector<T>> wptr;
	std::size_t curr;
};

template <typename T>
std::shared_ptr<std::vector<T>>
BlobPtr<T>::check (std::size_t i, const std::string& msg) const
{
	auto ret = wptr.lock (); //判断wptr是否绑定了Blob
	if (!ret)
		throw std::runtime_error ("unbound BlobPtr");
	if (i >= ret->size ())
		throw std::out_of_range (msg);
	return ret;
}

template <typename T>
BlobPtr<T>& BlobPtr<T>::operator++ () {
	check (curr, "increment past end of BlobPtr"); //先判断后加
	++curr;
	return *this;
}

template <typename T>
BlobPtr<T>& BlobPtr<T>::operator-- () {
	--curr; //先减之后, 如果为0, 再减就是大整数
	check (curr, "decrement past begin of BlobPtr"); //先减后判断
	return *this;
}

template <typename T>
BlobPtr<T> BlobPtr<T>::operator ++(int)
{
	BlobPtr ret = *this;
	++*this; //使用重载的前缀++
	return ret;
}

template <typename T>
BlobPtr<T> BlobPtr<T>::operator --(int)
{
	BlobPtr ret = *this;
	--*this; //使用重载的前缀--
	return ret;
}

int main (void) {
	std::cout << "Hello Mystra!" << std::endl;
	Blob<int> ia;
	Blob<int> ia2 = {0, 1, 2, 3, 4};
	std::cout << "ia2[2] = " << ia2[2] << std::endl;
	BlobPtr<int> pia = ia2;
	std::cout << "*(++pia) = " << *(++pia) << std::endl;
	return 0;
}



  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Caroline S

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值