template的用法(超详细)

您所在的位置:网站首页 杭州风景手抄报 template的用法(超详细)

template的用法(超详细)

#template的用法(超详细)| 来源: 网络整理| 查看: 265

首先总结一下,template其实是C++的一种语法糖,本意是去简化程序员的工作(但我认为语法实在有点繁琐,反而加大了开发成本)。

template的运用场景主要是以下部分,假设我们想写一个交换函数swap

void swap(int *a,int *b){ int temp = *a; *a = *b; *b = temp; }

那你这个交换函数只能用在int的数据类型吧,float呢?float就不用交换了吗?所以我们还得写以下代码  

void Swap(float *a, float *b){ float temp = *a; *a = *b; *b = temp; }

对吧,然后还有char类型的swap,还有bool类型的类型的swap,全都要写.....此时你一拍桌子,不写了!什么垃圾玩意!

然后你百度一下,发现了有template这玩意。

那用template会不会更方便嘞,那必须的呀,只用写以下代码。

//声明时这样 template void Swap(T *a, T *b){ T temp = *a; *a = *b; *b = temp; } //调用时这样 int a=10,b=20; swap(&a,&b);

此时,我们就不用针对每种类型都写一遍swap了(template会告诉编译器:这个a是int!这个b也是int!),这就是template的作用。

 

template其实比较关键的事函数模板和类模板,其他的都是在这些基础上延伸而来的。

1.函数模板声明

函数模板顾名思义,就是template用在函数上

定义的时候吧,咱就这样定义

template void swap(const T*a,const T*b) { T temp = *a; *a = *b; *b = temp; } 2.函数模板调用 

然后用起来吧,咱这样用,这时候你可以直接调用swap,这个咱叫隐式调用,就是你不用扯着嗓子喊:这个a是int!这个b也是int!的意思,稍后会讲到。

int main() { int a=10,b=20; float c=30,d=40; swap(&a,&b); swap(&c,&d); return 0; } 3.inline函数模板

如果你想把你的函数声明为inline提高效率,那么参考下面

inline关键字放在template之后,函数类型之前

//正确写法 templateinline T swap(const T*a,const T*b) //错误写法 inline templateT swap(const T*a,const T*b)

2.类模板 类模板声明 templateclass Queue{ public: Queue(); Type &front(); const Type &front()const; void push(const Type &); void pop(); bool empty()const private: ... }; 类模板定义

和咱的函数模板不同啊,我们的类模板需要加个括号(显式)告诉编译器老子是啥类型。

queueqi;//什么是显式,在定义时加个括号告诉他老子是int就是显式 Queueqc; Queueqs;

3.非类型模板形参

非类型模板形参实际上传的就不是类型了,而是传一个具体的数字!

(待补充)

4.模板特化

有些时候,我们编写的模板定义并不总是适用于所有类型

template int compare(const T&v1,const T&v2) { if(v1v2)return 1; return 0; }

当这个函数的参数类型是C风格字符串时,这个函数不能正常工作(这个函数将比较两个指针在内存中的相对位置,但没有比较指针指向对象的大小),这时候我们必须提供一个针对C风格字符串的特殊定义,这就是模板特化

1.函数模板的特化

特化的形式如下:

关键字tempalte后面接一对空的尖括号(< >)函数名后接模板名和一对尖括号,尖括号中指定这个特化定义的模板形参函数形参表函数体 template int compare(const char *const &v1,const char *const &v2) { return strcmp(v1,v2); } 1.声明模板特化

与任意函数一样,函数模板特化可以声明而无须定义。

template int compare(const char *const &,const char *const &); 2.函数重载与模板特化

如果在特化中省略空的模板形参表template,那么结果是函数的重载而不是模板特化

int compare(const char *const&,const char *const&); //声明了该函数的重载版本而不是模板版本 3.特化的作用域规则

在调用模板的这个特化版本之前,特化的声明必须在作用域中

template int compare(const T&t1,const T& t2) { ... } int main() { int i=compare("hello","world"); ... } template int compare(const char *const &s1,const char *const &s2) { ... }

这个程序有错误,这个函数将会调用未特化的原模板函数

特化出现在对该模板实例的调用之后是错误的

2.类模板的特化 1.类特化的定义 template class Queue{ public: void push(const char *); void pop();{real_queue.pop();} bool empty()const{return real_queue.empty();} std::string front(){return real_queue.front();} const std::string &front()const{return real_queue.front();} private: Queuereal_queue; };

类模板特化应该与它所特化的模板定义相同的接口,否则当用户试图使用未定义的成员时会感到奇怪

2.在类特化外部定义成员 void Queue::push(const char*val) { return real_queue.push(val); }

在类特化外部定义成员时,成员之前不能加template标记

3.特化成员而不特化类 template void Queue::push(const char *const &val) { ... } template void Queue::pop() { ... }

现在,类类型Queue将从通用类模板定义实例化而来,而push和pop函数例外。调用Queue对象的push或pop函数时,将调用特化版本;调用其他任意成员时,将从类模板为const char*实例化一个通用版本。

4.类模板的部分特化

如果类模板有一个以上的模板形参,我们也许想要特化某些模板形参而非全部,使用类模板的部分特化可以做到这一点:

template class some_template{ //... }; //部分特化 template class some_template{ //... }

使用类模板的部分特化 some_templatefoo;//使用类模板 some_templatebar;//使用部分特化

1.foo的实例化类型与提供的部分特化类型不匹配,因此,foo的类型必然从通用类模板实例化

2.bar选择部分特化模板来实例化。当声明了部分特化的时候,编译器将为实例化选择最特化的模板定义,当没有部分特化可以使用的时候,就使用通用模板定义。

ps:函数模板是没有部分特化的,如果声明了一个部分特化的函数模板,编译器会报错



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3