【C++ Primer 第16章】1. 定义模板 (一)
类模板
#include<iostream>
#include<vector>
#include<memory>
using namespace std; template <typename T> class BlobPtr;
template <typename T> class Blob;
template <typename T> bool operator==(const Blob<T>&, const Blob<T>&); template<typename T> class Blob {
friend class BlboPtr;
friend bool operator==(const Blob<T>&, const Blob<T>&);
public:
typedef typename vector<T>::size_type size_type; Blob();
Blob(initializer_list<T> il); size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
void push_back(const T&) { data->push(t); }
void push_back(T &&t) { data->push_back(std::move(t)); } void pop_back();
T& back();
T& opearator[](size_type i); private:
shared_ptr<vector<T>> data;
void check(size_t i, const string &msg)
}; template <typename T>
Blob<T>::Blob(): data(make_shared<vector<T>>()) {} template <typename T>
Blob<T>::Blob(initializer_list<T> il): data(make_shared<vector<T>>(il)) {} temlate <typename T>
void Blob<T>::check(size_type i, const string &msg) const
{
if (i >= data->size())
throw out_of_range(msg);
}
template <typename T>
void Blob<T>::pop_back()
{
check(, "pop_back on empty Blob");
data->pop_back();
} template <typename T>
T& Blob<T>::back()
{
check(, "back om empty Blob");
return data->back();
} template <typename T>
T& operator[](size_type i)
{
check(i,"subscript out of range");
return (*data)[i];
} /*--------------------------BlobPtr----------------------------------------------*/ template <typename T> BlobPtr {
public:
BlobPtr(): curr() {}
BlobPtr(Blob<T> &a, size_r sz = ): wptr(a.data), curr(sz) {} T& opearator*() const; BlobPtr& operator++(); //后缀自增
BlobPtr& opearator--();
BlobPtr& opearator++(int); //前缀自减
BlobPtr& opearator--(int); private:
size_t curr;
weak_ptr<vector<T>> wptr;
shared_ptr<vector<T>> check(size_t, const string&) const
}; template <typename T>
shared_ptr<vector<T>> BlobPtr<T>::check(size_t i, const string &msg) const
{
auto ret = wptr.lock();
if (!ret)
throw runtime_error("unbind BlobPtr");
if (i >= ret->size())
thow out_of_range(msg);
} template <typename T>
T& BlobPtr*() const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];
} template <typename T>
BlobPtr<T>& BlobPtr<T>::operator--()
{
--curr;
check(curr, "decrement past bengin of BlobPtr");
return *this;
} template <typename T>
BlobPtr<T>& BlobPtr<T>::opearator++()
{
check(curr, "unbound BlobPtr");
++curr;
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;
}
template <typename T> class Pal; // 前置申明,在将模板的一个特例声明为友元关系时要用到
class C { // C是一个普通的非模板类
friend class Pal<C>; // 用C实例化的Pal是C的一个友元 template <typename T> friend class Pal2; // pal2的所有实例都是C的友元;这种情况无需前置申明
}; template <typename T> class C2 { // C2本身是一个类模板
friend class Pal<T>; // C2的每个实例将相同实例化的Pal声明为友元
template <typename X> friend class Pal2; // Pal2的所有实例都是C2的每个实例的友元,不需要前置声明
friend class Pal3; // pal3是一个非模板类,它是C2所有实例的友元
// 不需要Pal3的前置声明
};
控制实例化
• 模板在使用时才会被实例化,相同的实例可能出现在对各对象文件中。
• 当多个独立编译的源文件使用了相同的模板,并提供了相同的参数。那么每个文件都会有该模板的一个实例,在大系统中,这会增加额外开销。
• 通过显示实例化,避免这种开销。
extern template class Blob<string> //声明
template int compare(const int&, const int&) //定义
【C++ Primer 第16章】1. 定义模板 (一)的更多相关文章
- 【C++ Primer 第16章】2. 模板实参推断
模板实参推断:对于函数模板,编译器利用调用中的函数实参来确定模板参数,从函数实参来确定模板参数的过程被称为模板实参推断. 类型转换与模板类型参数 与往常一样,顶层const无论在形参中还是在是实参中, ...
- [C++ Primer] : 第16章: 模板与泛型编程
面向对象编程(OOP)和泛型编程都能处理在编写程序时不知道类型的情况, 不同之处在于: OOP能处理类型在程序运行之前都未知的情况, 而在泛型编程中, 在编译时就能获知类型了. 函数模板 模板是C++ ...
- 【C++ Primer 第7章】定义抽象数据类型
参考资料 1. C++Primer #7 类 Sales_data类 Sales_data.h #include<iostream> #include<string> clas ...
- 【C++ Primer 第15章】定义派生类析构函数
学习资料 • 基类和派生类析构函数执行顺序 定义派生类析构函数 [注意]定义一个对象时先调用基类的构造函数.然后调用派生类的构造函数:析构的时候恰好相反:先调用派生类的析构函数.然后调用基类的析构函数 ...
- 【C++ Primer 第15章】定义派生类拷贝构造函数、赋值运算符
学习资料 • 派生类的赋值运算符/赋值构造函数也必须处理它的基类成员的赋值 • C++ 基类构造函数带参数的继承方式及派生类的初始化 定义拷贝构造函数 [注意]对派生类进行拷贝构造时,如果想让基类的成 ...
- C++ primer plus读书笔记——第16章 string类和标准模板库
第16章 string类和标准模板库 1. string容易被忽略的构造函数: string(size_type n, char c)长度为n,每个字母都为c string(const string ...
- C++ Primer 5th 第16章 模板与泛型编程
模板是C++中泛型编程的基础,一个模板就是创建一个类或者函数的蓝图或者说公式. C++模板分为函数模板和类模板. 类模板则可以是整个类是个模板,类的某个成员函数是个模板,以及类本身和成员函数分别是不同 ...
- 【c++ Prime 学习笔记】第16章 模板与泛型编程
面向对象编程(OOP)和泛型编程(GP)都能处理在编写程序时类型未知的情况 OOP能处理运行时获取类型的情况 GP能处理编译期可获取类型的情况 标准库的容器.迭代器.算法都是泛型编程 编写泛型程序时独 ...
- Linux就这个范儿 第16章 谁都可以从头再来--从头开始编译一套Linux系统 nsswitch.conf配置文件
Linux就这个范儿 第16章 谁都可以从头再来--从头开始编译一套Linux系统 nsswitch.conf配置文件 朋友们,今天我对你们说,在此时此刻,我们虽然遭受种种困难和挫折,我仍然有一个梦 ...
随机推荐
- mac下chrome快捷键
打开开发者工具:alt + command + I: 打开“JavaScript 控制台”:⌘-Option-J: 打开当前网页的源代码:⌘-Option-U: 刷新页面:command + R: m ...
- 构建eureka-server异常ClassNotFoundException: org.springframework.boot.context.embedded.FilterRegistrationBean
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.embedded.FilterRegistr ...
- JS控制CSS3,添加浏览器兼容前缀
不同浏览器对于有些css3属性名字定义的时候,会带上特有的前缀,所以在css编写的时候,经常会一个属性写多个不同的前缀进行兼容.比如: div { transform: rotate(30deg); ...
- MySQL与宿主Linux之间交互式执行命令
在MySQL里面执行Linux的命令并返回结果 system commands root@localhost 11:36:23> system cal March 2017 Su Mo Tu W ...
- Redis详解(一)冰叔带你了解Redis
Redis 是一种基于 键值对 的 NoSQL 数据库.与很多键值对数据库不同,Redis 提供了丰富的 值数据存储结构,包括 string(字符串).hash(哈希).list(列表).set ...
- listcontrolc插入列时,出现断言错误
原因:窗口还未创建,就对listcontrol进行了操作 解决方案:在初始化函数中 添加CDialogEx::OnInitDialog();
- VS中修改工程名的解决方案
VS中修改工程名的解决方案: 一.先修改工程名/解决方案名(在VS中修改即可)举例,原先的工程名为OldProject 想要改成NewProject1.找到工程/解决方案所在的文件夹(已工程名/解 ...
- HttpWebRequest post 提交 C#的WebBrowser操作frame如此简单 WebClient 提交
//http://www.cnblogs.com/cgli/archive/2011/04/09/2010497.html System.Net.ServicePointManager.Expect1 ...
- 【摘】SVN提交与版本冲突
一般性解决办法 1.要提交的内容备份到项目之外[为还原版本做准备] 2.还原[回到之前版本] 3.更新[更新版本号和版本] 4.填充内容[即 将自己之前备份的内容填充项目对应处] 5.提交 6.OK ...
- javaScript之表格操作<一:新增行>
DOM表格系列操作 /** * 添加表格行 * @function 本接口可以用于:在表格tbody部分新增任意数量,任意样式的行HTML结构; * @name addTableLines * @au ...