zoukankan      html  css  js  c++  java
  • C++类模板

    在上篇文章(C++函数模板)中,主要介绍了C++中函数模板,与函数相似,类也可以被一种或多种类型参数化。容器类就是一个具有这种特性的典型的例子,

    本文地址:http://www.cnblogs.com/archimedes/p/cpp-class-template.html,转载请注明源地址。

    以下通过设计一个类模板Stack的实现来说明:

    类模板Stack的实现

    #include<iostream>
    #include<vector>
    #include<stdexcept>
    #include<string>
    #include<cstdlib>
    using namespace std;
    
    template<typename T>
    class Stack
    {
    private:
        vector<T> elems;  //存储元素的容器
    public:
        void push(T const&);  //压入元素
        void pop();           //弹出元素
        T top() const;        //返回栈顶元素
        bool empty() const {  //返回栈是否为空
            return elems.empty();
        }
    };
    
    template<typename T>
    void Stack<T>::push(T const& elem)
    {
        elems.push_back(elem);
    }
    
    template<typename T>
    void Stack<T>::pop()
    {
        if(elems.empty()) {
            throw out_of_range("Stack<>::pop(): empty stack");
        }
        elems.pop_back();
    }
    
    template<typename T>
    T Stack<T>::top() const
    {
        if(elems.empty()) {
            throw out_of_range("Stack<>::top(): empty stack");
        }
        return elems.back();
    }

    可以发现,类模板Stack<>是通过C++标准库vector<>来实现的,我们可以不需要亲自设计内存管理、拷贝构造函数和赋值运算

    类模板Stack的使用

    为了使用类模板对象,必须显式地指定模板实参,下面的例子展示了如何使用类模板Stack<>:

    int main()
    {
        try{
            Stack<int> intStack;
            Stack<string> stringStack;
    
            intStack.push(7);
            cout<<intStack.top()<<endl;
    
            stringStack.push("hello");
            cout<<stringStack.top()<<endl;
            stringStack.pop();
            stringStack.pop();
        }
        catch(exception const& ex) {
            cerr<<"Exception: "<<ex.what()<<endl;
            //return EXIT_FAILURE;
        }
        cin.get();  
        return 0;
    }

     通过声明类型Stack<int>,在类模板内部就可以用int实例化T。因此,intStack是一个创建自Stack<int>的对象,它的元素存储于vector,且类型为int,类似,如果声明和使用Stack<string>将会创建相应的对象。
    对于类模板,成员函数只有在被使用的时候才被实例化。

    显然,这样可以节省时间和空间,另一个好处是:对于那些“未能提供所有成员函数中所有操作的”类型,你可以使用该类型来实例化类模板,只要对那些“未能提供某些操作的”成员函数,模板内部不使用就可以。

    你可以像使用其他任何类型一样地使用实例化后的类模板类型(例如Stack<int>),只要它支持所调用的操作就可以:

    void foo(Stack<int> const& s)
    {
        Stack<int> istack[10];
        ...
    }

    借助于typedef,可以方便的使用类模板:

    typedef Stack<int> IntStack;
    void foo(IntStack const& s)
    {
        IntStack<int> istack[10];
        ...
    }

    类模板的特化
    可以使用模板实参来特化类模板,和函数模板的重载类似,通过特化类模板,你可以优化基于某种特定类型的实现,或者克服某种特定类型在实例化类模板时所出现的不足。

    为了特化一个类,你必须在起始处声明一个template<>,接下来声明用来特化类模板的类型:

    template<>
    class Stack<string> {
    private:
        deque<string> elems;
    public:
        void push(string const&);
        void pop();
        string top() const;
        bool empty() const {
            return elems.empty();
        }
    };
    
    void Stack<string>::push(string const& elem)
    {
        elems.push_back(elem);
    }
    
    void Stack<string>::pop()
    {
        if(elems.empty()) {
            out_of_range("Stack<string>::pop(): empty stack");
        }
        elems.pop_back();
    }
    
    string Stack<string>::top()
    {
        if(elems.empty()) {
            out_of_range("Stack<string>::top(): empty stack");
        }
        return elems.back();
    }
  • 相关阅读:
    AE 线编辑
    ArcEngine判断要素(feature)是否为multipart feature及分解(炸开)代码
    AE二次开发技巧之撤销、重做
    ArcEngine数据编辑--选择要素
    java语言体系的技术简介之JSP、Servlet、JDBC、JavaBean(Application)
    MVC开发模式详解
    数据库设计中常见表结构的设计技巧
    Eclipse 保存文件时自动格式化代码
    优化你的java代码性能
    Hibernate 与mybatis的区别
  • 原文地址:https://www.cnblogs.com/wuyudong/p/cpp-class-template.html
Copyright © 2011-2022 走看看