【ThinkingInC++】68、模板介绍
2014-10-07 18:41
323 查看
第十六章 模板介绍
模板中的常量
/** * 书本:【ThinkingInC++】 * 功能:模板中的常量 * 时间:2014年10月7日18:45:01 * 作者:cutter_point */ #include<cstdio> #include<iostream> #include"../require.h" usingnamespace std; template<classT, int size=100> //这个size不写到类中,但是使用的时候就如同是成员函数中的 class Array { T array[size]; public: T& operator[] (int index) //重载下标操作符 { //验证数据越界 require(index >= 0 &&index<size, "Index out of range"); return array[index]; } int length() const { return size; } }; classNumber { float f; //等会作为数据类型,当成模板的参数 public: Number(float ff=0.0f) : f(ff) {} Number& operator=(const Number&n) //赋值运算操作符 { f=n.f; return *this; //最后返回当前的对象,这是一个值拷贝,吧外面的Number对象拷贝到这个对象 } operator float() const { return f; } //float(),返回当前值 friend ostream&operator<<(ostream& os, const Number& x) { return os<<x.f;} //输出,友元 }; template<classT, int size=20> classHolder { Array<T, size>* np; public: Holder() : np(0) {} T& operator[] (int i) { require(0 <= i &&i<size); //判定是不是在范围内 if(!np) np=new Array<T,size>; //判定是不是为空,如果为空的话,就创建一个,不为空直接返回值 return np->operator[](i); //返回创建的对象的值 } int length() const { return size; } ~Holder() { delete np; } }; intmain(int argc, char *argv[]) { Holder<Number> h; for (int i=0 ; i<20 ; ++i) { h[i]=i; } for (int j=0 ; j<20 ; ++j) { cout<<h[j]<<endl; } return 0; }
类Holder很像Array,只是它有一个指向Array的指针,而是推迟到第一次访问的时候,这个叫懒惰初始化。
作为模板的Stash和Stack
头文件TStack.h
/** * 书本:【ThinkingInC++】 * 功能:这是用模板写一个栈类的头文件 * 1》使用嵌套类 * 2》添加构造函数,析构函数,添加,删除,弹出 * 时间:2014年10月7日18:45:24 * 作者:cutter_point */ #ifndefTSTACK_H_INCLUDED #defineTSTACK_H_INCLUDED template<classT> class Stack { struct Link { T* data; //指向数据成员 Link* next; //指向下一个节点 Link(T* dat, Link* nxt) : data(dat),next(nxt) {} }*head; public: Stack() : head(0) {} //构造函数 ~Stack() { while(head) delete pop(); //调用pop来回收空间,只要还有剩余的节点那么就回收 } void push(T* dat) //添加数据 { head=new Link(dat, head); //吧头节点向下压,吧新的节点作为头结点 } T* peek() const { return head ?head->data : 0; } //返回元素但是不删除元素 T* pop() //返回并且删除元素 { if(head == 0) return 0; //如果头结点为空,那么直接返回 //如果不为空 //吧头结点的数据保存,有一个指针指向头节点 T* result=head->data; Link* oldHead=head; //断开头结点 head=head->next; //回收原来的头节点 delete oldHead; //返回原来节点的数据 return result; } }; #endif //TSTACK_H_INCLUDED
运行文件TStackTest.cpp:
/** * 书本:【ThinkingInC++】 * 功能:用模板栈实现对本文件的文件流读取 * 时间:2014年10月7日18:45:59 * 作者:cutter_point */ #include"TStack.h" #include"../require.h" #include<fstream> #include<iostream> #include<string> usingnamespace std; class X {//为了跟踪信息,反映Stack容器清除对象 public: //这里定义为虚函数是为了以后如果有派生类的话,对象可以存放相应的派生类 virtual ~X() {cout<<"~X"<<endl; } }; int main() { ifstream in("TStackTest.cpp"); assure(in, "TStackTest.cpp"); Stack<string> textlines; //存放所有的数据 string line; //存放一行 while(getline(in, line)) textlines.push(new string(line)); //存放进去,这里的参数是一个引用,所以必须创建一个新的string给它 //显示出来 string* s; for(int i=0 ; i<46 ; ++i) { //如果全部弹出了,那么直接跳出循环 if((s=(string*)textlines.pop()) ==0)break; cout<<*s<<endl; } delete s; //回收上面创建的s; Stack<X> xx; for(int j=0 ; j<10 ; ++j) xx.push(new X); return 0; }
头文件AutoCounter.h,报告自身的创建和销毁
/** * 书本:【ThinkingInC++】 * 功能:报告自身的创建和销毁 * 时间:2014年10月7日18:46:37 * 作者:cutter_point */ #ifndefAUTOCOUNTER_H_INCLUDED #defineAUTOCOUNTER_H_INCLUDED #include"../require.h" #include<iostream> #include<set> #include<string> classAutoCounter { static int count; //计数 int id; class CleanupCheck //嵌套类 { std::set<AutoCounter*> trace; public: void add(AutoCounter* ap) {trace.insert(ap); } //size_type erase( const key_type&key );删除等于key值的所有元素 //(返回被删除的元素的个数)。 void remove(AutoCounter* ap) {require(trace.erase(ap) == 1, "这个数值删除超过1次"); } ~CleanupCheck() { std::cout<<"~CleanupCheck()"<<std::endl; require(trace.size() == 0, "这个AutoCounter没有清除干净"); } }; static CleanupCheck verifier; //这个其实就是一个set,外加一些操作 //吧构造函数私有,拷贝赋值函数私有,拷贝赋值运算符私有,避免外部创建对象 AutoCounter() : id(count++) { verifier.add(this); //吧当前对象加入到set中 std::cout<<"created["<<id<<"]"<<std::endl; } AutoCounter(const AutoCounter&); void operator=(const AutoCounter&); public: static AutoCounter* create() { return newAutoCounter(); } ~AutoCounter() {std::cout<<"destroying["<<id<<"]"<<std::endl;verifier.remove(this); } friend std::ostream&operator<<(std::ostream& os, const AutoCounter& ac) //引用 { return os<<"AutoCounter"<<ac.id; } friend std::ostream&operator<<(std::ostream& os, const AutoCounter* ac) //引用 { return os<<"AutoCounter"<<ac->id; } }; #endif //AUTOCOUNTER_H_INCLUDED
感想:
1、对于代码的目的是为了简化问题而不是让问题复杂化。所以以后有什么不会的可以从这个方面去探讨。
相关文章推荐
- 学习总结: C++ 模板 (thinking in C++)
- 【ThinkingInC++】73、深入理解模板
- 混沌 IN C++::模板参数的奥秘
- Thinking in C++ 阅读笔记(第一章)
- Thinking in C++ 第二版 简体中文版 前言
- Thinking in C++ learning(3)-----隐藏实现
- Thinking in C++ learning(2)-----Data Abstract
- thinking in c++ 卷2
- thinking in c++ 读书笔记:c与c++之区别
- Thinking in C++ 下载
- Thinking in C++读书笔记--7.2指针常量
- Thinking again in C++(二)自赋值是非公断
- Thinking in C++ 阅读笔记(第三章)
- Thinking in C++ (1-2)
- Thinking in C++ (1-1)
- Thinking in C++ 简体中文第二版
- 混沌 IN C++::模板参数的奥秘
- 终于看完《Thinking in c++》第二版的第一卷了
- Thinking in C++ (1-4)
- Thinking in C++ learning(1)-----C in C++