• 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();
    }
  • 相关阅读:
    03 在百度地图上定位到指定位置
    01 如何将百度地图加入IOS应用程序?
    三个字理解委托机制
    iOS 应用程序打包、真机调试 方法
    在读iOS官方文档时,里面有很多你不懂的单词,不要担心
    用“大控件”与“大数据类型”思想来理解view Cotroller
    04 将当前位置用大头针标注到百度地图上
    02 使用百度地图获得当前位置的经纬度
    专注分享思考过程
    像孙正义为了练英语坚决不说日语一样。我也应该有坚决不看中文文档的心!
  • 原文地址:https://www.cnblogs.com/wuyudong/p/cpp-class-template.html
Copyright © 2020-2023  润新知