您的位置:首页 > 编程语言 > C语言/C++

【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、对于代码的目的是为了简化问题而不是让问题复杂化。

所以以后有什么不会的可以从这个方面去探讨。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: