• 【c++ templates读书笔记】【2】类模板


    1、类模板的声明

    template <typename T>
    class Stack{
      ...
    }
    

    2、在类模板内部,T可以像其他任何类型一样,用于声明成员变量和成员函数。

    template <typename T>
    class Stack{
    private:
    	std::vector<T> elemes;    // 存储元素的容器
    
    public:
    	Stack();                  // 构造函数
    	void Push(const T& e);   // 压入元素
    	void Pop();              // 弹出元素
    	T Top() const;        // 返回栈顶元素
    };

    这个类的类型是Stack<T>,其中T是模板参数。

    3、类模板具体例子

    #include<iostream>
    #include<vector>
    #include<string>
    using namespace std;
    
    template<typename T>
    class Stack{
    private:
    	vector<T> vec;
    public:
    	void push(T const& elem);
    	void pop();
    	T top() const;
    	bool empty() const{
    		return vec.empty();
    	}
    };
    template<typename T>
    void Stack<T>::push(T const& elem){
    	vec.push_back(elem);
    }
    template<typename T>
    void Stack<T>::pop(){
    	if (vec.empty()){
    		throw out_of_range("Stack<>::pop():empty stack");
    	}
    	vec.pop_back();
    }
    template<typename T>
    T Stack<T>::top() const{
    	if (vec.empty()){
    		throw out_of_range("Stack<>::pop():empty stack");
    	}
    	return vec.back();
    }
    
    int main(){
    	try{
    		Stack<int> istk;
    		istk.push(7);
    		istk.push(8);
    		istk.push(9);
    		cout << istk.top() << endl;
    		istk.pop();
    		cout << istk.top() << endl;
    
    		Stack<string> sstk;
    		sstk.push("aaa");
    		sstk.push("bbb");
    		sstk.push("ccc");
    		cout << sstk.top() << endl;
    		sstk.pop();
    		cout << sstk.top() << endl;
    	}
    	catch (exception const& ex){
    		cerr << "Exception:" << ex.what() << endl;
    		return EXIT_FAILURE;
    	}
    
    	system("pause");
    	return 0;
    }

    对于类模板,成员函数只有被调用的时候才被实例化。如果类模板中含有静态成员,那么用来实例化的每种类型,都会实例化静态成员。

    4、类模板的特化

    为了特化一个类模板,要在起始处声明一个template<>.接下来声明用来特化模版的类型,这个类型被用作模版实参。

    //类模板的特化
    template<>
    class Stack<string>{
    private:
    	deque<string> deq;
    public:
    	void push(string const& elem);
    	void pop();
    	string top() const;
    	bool empty() const{
    		return deq.empty();
    	}
    };
    void Stack<string>::push(string const& elem){
    	deq.push_back(elem);
    }
    void Stack<string>::pop(){
    	if (deq.empty()){
    		throw out_of_range("Stack<>::pop():empty stack");
    	}
    	deq.pop_back();
    }
    string Stack<string>::top() const{
    	if (deq.empty()){
    		throw out_of_range("Stack<>::pop():empty stack");
    	}
    	cout << "模板的特化:";
    	return deq.back();
    }
    

    5、局部特化

    template<typename T1, typename T2>
    class MyClass{
      ...
    };
    // 局部特化,两个模板参数类型相同
    template<typename T>
    class MyClass<T, T>{
      ...
    };
    // 局部特化,第2个模板参数是int
    template<typename T>
    class MyClass<T, int>{
      ...
    };
    // 局部特化,两个模板参数都是指针类型
    template<typename T1, typename T2>
    class MyClass<T1*, T2*>{
      ...
    };
    

    6、缺省模板实参

    可以为类模板的参数定义缺省值,这些值被称为缺省模板实参,还可以引用之前的模板参数。

    下面例子中的vector<T>就是缺省模板实参

    #include<iostream>
    #include<vector>
    #include<string>
    #include<deque>
    using namespace std;
    
    template<typename T,typename Container=vector<T>>
    class Stack{
    private:
    	Container container;
    public:
    	void push(T const& elem);
    	void pop();
    	T top() const;
    	bool empty() const{
    		return container.empty();
    	}
    };
    template<typename T, typename Container>
    void Stack<T,Container>::push(T const& elem){
    	container.push_back(elem);
    }
    template<typename T, typename Container>
    void Stack<T, Container>::pop(){
    	if (container.empty()){
    		throw out_of_range("Stack<>::pop():empty stack");
    	}
    	container.pop_back();
    }
    template<typename T, typename Container>
    T Stack<T, Container>::top() const{
    	if (container.empty()){
    		throw out_of_range("Stack<>::pop():empty stack");
    	}
    	return container.back();
    }
    
    int main(){
    	try{
    		Stack<int> istk;
    		istk.push(7);
    		istk.push(8);
    		istk.push(9);
    		cout << istk.top() << endl;
    		istk.pop();
    		cout << istk.top() << endl;
    
    		Stack<string,deque<string>> sstk;
    		sstk.push("aaa");
    		sstk.push("bbb");
    		sstk.push("ccc");
    		cout << sstk.top() << endl;
    		sstk.pop();
    		cout << sstk.top() << endl;
    	}
    	catch (exception const& ex){
    		cerr << "Exception:" << ex.what() << endl;
    		return EXIT_FAILURE;
    	}
    
    	system("pause");
    	return 0;
    }
    

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    AndroidのActivity启动模式
    Android 垃圾回收,用软引用建立缓存
    如何在eclipse的配置文件里指定jdk路径
    Chrome浏览器扩展开发系列之二:Google Chrome浏览器扩展的调试
    Chrome浏览器扩展开发系列之三:Google Chrome浏览器扩展的架构
    Chrome浏览器扩展开发系列之四:Browser Action类型的Chrome浏览器扩展
    Chrome浏览器扩展开发系列之五:Page Action类型的Chrome浏览器扩展
    Chrome浏览器扩展开发系列之六:options 页面
    手把手教你开发Chrome扩展三:关于本地存储数据
    手把手教你开发Chrome扩展二:为html添加行为
  • 原文地址:https://www.cnblogs.com/ruan875417/p/4921347.html
Copyright © 2020-2023  润新知