1、关键字typename
引入关键字typename是为了说明:模板内部的标识符可以是一个类型。当某个依赖与模板参数的名称是一个类型时,就应该使用typename。
template<T> class MyClass{ typename T::SubType * ptr; // typename说明SubType是定义于T内的一种类型,如果不使用typename,SubType会被认为是T的一个静态成员 ... };
2、使用this->
对于那些在基类中声明,并且依赖于模板参数的符号(函数或变量等),应该在它们前面使用this->或者Base<T>::。
#include<iostream> using namespace std; template<typename T> class Base{ public: void exit(){ cout << "exit" << endl; } }; template<typename T> class Derived:Base<T>{ public: void exitDerived(){ this->exit();//但VS 2013中直接用exit()也能正确运行 } }; int main(){ Derived<int> d; d.exitDerived(); system("pause"); return 0; }
3、成员模板
嵌套类和成员函数都可以作为模板,例子:#include<iostream> #include<deque> using namespace std; template<typename T> class Stack{ private: deque<T> deq; public: void push(T const& elem); void pop(); T top() const; bool empty() const{ return deq.empty(); } template<typename T2>//成员模板 Stack<T>& operator=(Stack<T2> const& op2); }; template<typename T> void Stack<T>::push(T const& elem){ deq.push_back(elem); } template<typename T> void Stack<T>::pop(){ if (deq.empty()){ throw out_of_range("Stack<>::pop():empty stack"); } deq.pop_back(); } template<typename T> T Stack<T>::top() const{ if (deq.empty()){ throw out_of_range("Stack<>::pop():empty stack"); } return deq.back(); } template<typename T> template<typename T2> Stack<T>& Stack<T>::operator=(Stack<T2> const& op2){ if ((void*)this == (void*)&op2) return *this; Stack<T2> tmp(op2); deq.clear(); while (!tmp.empty()){ deq.push_front(tmp.top()); tmp.pop(); } return *this; } int main(){ try{ Stack<float> istk; istk.push(7.2); istk.push(8.3); istk.push(9.4); cout << istk.top() << endl; istk.pop(); cout << istk.top() << endl; Stack<int> sstk; sstk = istk; 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、模板的模板参数
模板参数本身是模板,则该参数是模板的模板参数。函数模板不支持模板的模板参数。
例子:
#include<iostream> #include<deque> #include<vector> using namespace std; //这里Container是模板的模板参数 template<typename T,template<typename ELEM,typename=allocator<ELEM>> class Container=deque> class Stack{ private: Container<T> container; public: void push(T const& elem); void pop(); T top() const; bool empty() const{ return container.empty(); } template<typename T2, template<typename ELEM2, typename = allocator<ELEM2>> class Container2> Stack<T, Container>& operator=(Stack<T2, Container2> const& op2); }; template<typename T, template<typename ELEM, typename = allocator<ELEM>> class Container> void Stack<T,Container>::push(T const& elem){ container.push_back(elem); } template<typename T, template<typename ELEM, typename = allocator<ELEM>> class Container> void Stack<T, Container>::pop(){ if (container.empty()){ throw out_of_range("Stack<>::pop():empty stack"); } container.pop_back(); } template<typename T, template<typename ELEM, typename = allocator<ELEM>> class Container> T Stack<T, Container>::top() const{ if (container.empty()){ throw out_of_range("Stack<>::pop():empty stack"); } return container.back(); } template<typename T, template<typename ELEM, typename = allocator<ELEM>> class Container> template<typename T2, template<typename ELEM2, typename = allocator<ELEM2>> class Container2> Stack<T, Container>& Stack<T, Container>::operator=(Stack<T2, Container2> const& op2){ if ((void*)this == (void*)&op2) return *this; Stack<T2, Container2> tmp(op2); container.clear(); while (!tmp.empty()){ container.push_front(tmp.top()); tmp.pop(); } return *this; } int main(){ try{ Stack<double> dstk; dstk.push(7.2); dstk.push(8.3); dstk.push(9.4); cout << dstk.top() << endl; dstk.pop(); cout << dstk.top() << endl; Stack<int> istk; istk = dstk; cout << istk.top() << endl; istk.pop(); cout << istk.top() << endl; } catch (exception const& ex){ cerr << "Exception:" << ex.what() << endl; return EXIT_FAILURE; } system("pause"); return 0; }
5、使用字符串作为函数模板的实参
#include<iostream> #include<string> using namespace std; template<typename T> T const& Max(T const& a, T const& b){ return a < b ? b : a; } int main(){ string s = "abc"; cout << Max("apple", "peach") << endl; //cout << Max("apple", "tomato") << endl;//错误,不同类型的实参 //cout << Max("apple", s) << endl;//错误,不同类型的实参 system("pause"); return 0; }
上述例子在VS2013中运行错误。
上述例子中后面两个调用错误的问题在于:由于长度的区别,这些字符串属于不同的数组类型,”apple”和”peach”具有相同的类型char const[6],”tomato”的类型是char const[7],因此只有第一个调用合法。但声明的是非引用参数,可以使用不同的字符串作为参数。
#include<iostream> #include<string> using namespace std; template <typename T> T Max(T a, T b){ return a < b ? b : a; } int main(){ string s = "abc"; cout << Max("apple", "peach") << endl; cout << Max("apple", "tomato") << endl;//正确,退化为相同的类型 //cout << Max("apple", s) << endl;//错误,不同类型的实参 system("pause"); return 0; }
上述第二个调用正确,原因是对于非引用类型的参数,在实参演绎的过程中,会出现数组到指针的类型转换。但是这里比较的是指针,而不是两个字符串的字典序。
版权声明:本文为博主原创文章,未经博主允许不得转载。