C++模板实战2:模板类
2013-12-29 17:10
330 查看
1 借助函数模板可以使算法脱于具体数据类型之外,借助模板类可以使数据结构脱于具体数据类型之外,从而专注于数据存取方法及数据间的关联方式,抽象的数据结构可以和具体数据类型无关。类模板和函数模板一样以template<typename...>开头,但是类模板实例化和函数模板实例化有一点不太一样,函数模板可以从函数参数自动推导模板参数从而可以省略模板参数的书写,而类模板即使有默认模板参数其<>还是不能省略,即最简单的类模板实例化也是类似于:class test<> one;其中采用默认模板参数可以省略参数单数<>不能省略。而且默认的模板参数尽量在安排在众模板参数的后面,因为模板实例化是按照参数位置来推导的。下面是一个简易的线程安全的栈操作(部分):
2 模板与继承:若基类是模板类,子类必须指定基类的模板参数,可以如下:
3 模板类与成员函数:模板类的成员函数可以使用和类模板相同的模板参数,也可以使用不同于类模板的参数。成员函数类外实现时要注意带上类模板的参数。实例如下:
4 类模板的静态成员:普通类中的静态成员在类的多次实例化对象中静态成员始终只有一份,在模板类中静态成员是否如此呢?首先模板类实例化后具有相同模板参数的实例化才是同样的类,那么相同的模板实例化代码共享同一份静态数据成员。如下:
5 友元模板类:友元耦合性太强,一般不怎么用,要用友元类模板可以如下:
6 嵌套模板实现tuple:std::pair表示一个二元组,tuple可以表示多元元组,C++11通过变长模板实现std::tuple,变长模板对模板参数包的解包对变长模板参数解析。这里通过嵌套实现tuple,代码如下:
PI 3.14 1 p
#include<iostream> #include<memory> #include<mutex> #include<utility> using namespace std; template<typename T> class myStack{//只提供了push和try_pop操作 public: myStack():head(nullptr){} myStack(myStack& one)=delete;//防止多个栈共享head myStack& operator=(const myStack& one)=delete; ~myStack(){ while(head){ node* temp=head->next; delete head; head=temp; } } void push(T& value){ node* new_node=new node(value); unique_lock<mutex> lock(m); new_node->next=head; head=new_node; } bool try_pop(T& value){//栈内有元素则返回true,否则返回false,元素值通过函数参数引用返回 unique_lock<mutex> lock(m); if(head){ value=move(*head->data); head=head->next; return true; } else{ return false; } } bool empty() const{ unique_lock<mutex> lock(m); return head==nullptr?true:false; } private: struct node{ shared_ptr<T> data; node* next; node(T& value):data(std::make_shared<T>(value)){} node():next(nullptr){} }; node* head; mutex m;//互斥量保护栈存取 }; int main(){ myStack<string> stackOne; string s("hello world"); stackOne.push(s); string temp; if(stackOne.try_pop(temp)) cout<<temp<<endl; return 0; }
2 模板与继承:若基类是模板类,子类必须指定基类的模板参数,可以如下:
template<typename T> class base;//模板基类 template<typename T> class derived1: public base<T>;//子类和基类使用共同的模板参数 template<typename T1,typename T2> class derived2:public base<T2>;//子类和基类模板参数不同 class derived3:public base<int>;//子类不是模板类,基类需实例化
3 模板类与成员函数:模板类的成员函数可以使用和类模板相同的模板参数,也可以使用不同于类模板的参数。成员函数类外实现时要注意带上类模板的参数。实例如下:
template<typename T> class test{ public: void fun(){cout<<"fun"<<endl;};//和类使用相同的模板参数且在类中实现 void fun1(); template<typename T1> void fun2(); }; template<typename T>//和类模板参数一样且类外实现 void test<T>::fun1(){cout<<"fun1"<<endl;} temlate<typename T>//类外实现注意带上类的模板参数 template<typename T1> void test<T>::fun2(){cout<<"fun2"<<endl;}
4 类模板的静态成员:普通类中的静态成员在类的多次实例化对象中静态成员始终只有一份,在模板类中静态成员是否如此呢?首先模板类实例化后具有相同模板参数的实例化才是同样的类,那么相同的模板实例化代码共享同一份静态数据成员。如下:
template<typename T> class test{ public: staitc int data; }; template<typename T> int test<T>::data=0;//静态成员的类外初始化 test<int> one; test<int> two;//one和two实例化后共享data的内存地址 test<double> three;
5 友元模板类:友元耦合性太强,一般不怎么用,要用友元类模板可以如下:
template<typename T> class test; class one{ public: template<typename T> friend class test; };
6 嵌套模板实现tuple:std::pair表示一个二元组,tuple可以表示多元元组,C++11通过变长模板实现std::tuple,变长模板对模板参数包的解包对变长模板参数解析。这里通过嵌套实现tuple,代码如下:
#include<iostream> #include<string> using namespace std; template<typename T,typename N> struct Tuple{ T value; N next; Tuple(T const& v,N const& n):value(v),next(n){} }; template<typename T,typename N> Tuple<T,N> push(T const& v,N const& n){ return Tuple<T,N>(v,n); } int main(){ using Tuple2=Tuple<int,char>; using Tuple3=Tuple<float,Tuple2>; using Tuple4=Tuple<string,Tuple3>; Tuple4 myTuple=push(string("PI"),push(3.14f,push(1,'p'))); cout<<myTuple.value<<" "<<myTuple.next.value<<" "<<myTuple.next.next.value<<" "<<myTuple.next.next.next<<endl; return 0; }程序输出:
PI 3.14 1 p
相关文章推荐
- VC dll的制作和使用
- C语言内存管理
- C++ 0x 使用 shared_ptr 自动释放, 防止内存泄漏
- 关联、组合、聚合、依赖关系比较
- C++中的运算符重载(一)
- 踢爆IT劣书出版黑幕——由清华大学出版社之《C语言入门很简单》想到的(2)
- Java中JNI的使用详解第六篇:C/C++中的引用类型和Id的缓存
- 《C++ Primer》读书笔记之“指针和const限定符”
- c语言中所有文件操作函数详解fopen、fwrite、fread、fgetc、fputc、fscanf、fprintf、ftell、fseek等函数
- c++与java访问符区别
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
- c语言的指针(一)
- Codeblock 配置C++11编译环境(windows平台下)
- 利用HandVu进行手部动作识别分析
- error: C++ preprocessor "/lib/cpp" fails sanity check错误解决方法
- 关于C++构造函数
- 转:C语言自增自減问题总结
- 在C++ GUI Qt中使用QCA进行安全性编程之三
- C++变量的左值和右值
- cppTest-8.2:虚析构函数探究&父类和子类的构造函数与析构函数的调用顺序