C++ 模板与泛型(2)
2016-01-26 15:37
519 查看
C++ 模板与泛型之类模板
一个类模板的每个实例都形成一个独立的类,与函数模板不同是,编译器无法推断实参类型,必须由程序员显示的提供模板实参作为额外信息。类模板的成员函数只在程序用到它的时候才进行实例化,这也就意味着,某种类型如果不能完全符合模板定义的所有操作,我们仍然能够使用该类型对模板进行实例化。
示例
在C++ Primer中
以
Blob和
BlobPtr两个模板为例对类模板进行说明,现整理完整代码
(注:之前提到过C++模板不支持分离式编译,所以声明和定义都在同一个.h文件中。)
[code]//Blob.h //该模板类通过shared_ptr对vector进行管理,并通过友元的BlobPtr伴随类对自己进行监控。 #ifndef BLOB_H_ #define BLOB_H_ #include <iostream> #include <vector> #include <memory> #include <string> #include "BlobPtr.h" template <typename> class BlobPtr; template <typename> class Blob; template <typename T> bool operator==(const Blob<T>&, const Blob<T>&); template <typename T> class Blob{ public: typedef T value_type; typedef typename std::vector<T>::size_type size_type; //construct 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); friend class BlobPtr < T > ;//友元声明 friend bool operator==<T>(const Blob<T>&, const Blob<T>&);//友元声明 private: std::shared_ptr<std::vector<T>> data; //若data[i]无效,则抛出msg 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)){} //check是否越界 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->pop_back(); } #endif
[code]//BlobPtr.h //该模板类维护指向Blob的弱引用,用来进行元素访问和监控Blob对象 #ifndef BLOBPTR_H_ #define BLOBPTR_H_ #include <iostream> #include<vector> #include <memory> #include "Blob.h" template <typename> class Blob; 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<T> operator++(int); BlobPtr<T> 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;//当前索引 }; //check函数 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; } #endif
编写
main,进行单步调试就很容易看到其实质是使用类模板参数对成员函数、成员vector及智能指针进行实例化的过程。
总结
类模板与函数模板类似,类模板的名字不是一个类型名,而是用来实例化类型的,一个实例化的类型需要程序员显示的提供模板实参,类模板的每个实例都形成一个独立的类。相关文章推荐
- C++:泛型编程 map(查询成绩)
- C++ 模板与泛型(1)
- 使用String逐个赋值字符
- C++事件处理中的__hook与__unhook用法详解
- C语言 文件操作4--文件结构体FILE的理解以及缓冲区再讲
- c++ sort()qsort()
- c/c++ 英语专业词汇表
- 为setup.py添加c:c++ 头文件或者库的搜索路径
- 深入浅出Windows 10 通用应用开发学习笔记(C++) 3-1
- Boost 学习之算法篇 is_partitioned
- XML文件的解析、读取和生成(C/C++、win7、VS2010)
- 详解C++编程中断言static_assert的使用
- C++下std::pair的使用?
- 一种动态开辟二维数组的办法
- Google C++编程风格指南(三)之作用域的相关规范
- Google C++编程风格指南(三)之作用域的相关规范
- win7 64位 VC++6.0 调试出错 解决办法
- C语言 文件操作3--文件重定向与扫描
- c++ stringstream的使用
- C语言的优点和缺点