你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

C++——函数模板

[复制链接]
gaosmile 发布时间:2020-8-23 22:24

( w/ s0 t) L5 l" F/ s
* U  X/ K9 K9 Y# K' S  u/ A  E

& ^$ p  G6 v2 I
一、函数模板的引出:
1、c++中有几种交换变量的方法:
(1)定义宏代码块
(2)定义函数
代码版本一:
#include <iostream>
! z$ s  F+ F/ S3 l+ f#include <string>3 n8 l1 x5 X' Q1 b4 X) }

. P% E$ L% j, y9 N) `. zusing namespace std;6 f+ X, q' b/ d& {& D% n9 g+ v

7 m+ y( y3 Y1 c* C" _#define SWAP(t,a,b)   \3 X$ F- b2 P4 N3 {' q
do                    \
* ~' L- q8 f5 a* h; m* g8 k{                     \
' Y) V, b+ P) x  O' Z# i     t c =a;          \3 {4 H+ q8 S/ K& p; s
     a =b;            \
! Y( I: G# O! B% f1 C     b = c;           \
1 m! X3 T8 C1 M" C. L}while(0)
7 H5 i5 [" V3 k& v: ]+ R) r% I9 ^4 @4 a$ y
int main()$ ?1 ]  H1 M1 k
{
5 t5 V. r  @; j0 X( w" x0 t     int a =2;
. U" N$ H5 {5 O. ~7 T1 {     int b =5;
  @& ~+ Q' p' H3 W5 H* Z0 m8 w: X' q/ w, j) @% W1 Q: z% N! q/ T% ?7 k
     SWAP(int , a , b );; {  Y: V9 k- i7 d/ U2 h0 R4 L9 {% N
     cout<<"a= "<<a<<endl;% `$ `! L" w6 g3 _9 ?2 O$ M8 \: {# |: B
     cout<<"b= "<<b<<endl;
0 O! [& Y2 ^+ Q$ a7 t
, U8 ?+ ]2 o1 [- H5 W4 v     double m =4;6 A6 d) \: D, M" z$ m7 c' i
     double n =6;
& G2 K: r( Y# O) V! [0 ~3 R1 R/ ]     cout<<"m = "<<m<<endl;
  z2 E" B5 u! C2 V1 v4 K4 b     cout<<"n= "<<n<<endl;
. W$ K: [8 u- g9 h# z: _% Q3 f
! N  m) R( ?/ \4 S: }     return 0;8 ~( a% p; D5 \# _( G

/ P8 G3 V9 t- V3 y  K& I/ C$ U) L}
+ n- O2 ^" u% J% @# ~! D# B- T
3 O2 O# [& \3 x! B
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out
, \1 P2 X2 I6 Q5 g) S2 W% c6 Pa= 51 b& l2 z) r" o! \; a; `8 ?
b= 26 X+ ^. s# g: {8 @
m = 4- |2 S* L9 {& l8 N& |, `
n= 6
8 H% b: W! A5 f1 ]6 u6 x3 @- P! g# D- F- F1 }# m
注解:我们看两个数值交换成功。
我们再用使用函数的方式来实现这个功能,当然以前我们在c语言里面使用指针传参方式来实现这种两个数值直接的交换,现在我们利用c++里面更加高级的方式来实现,就是使用引用来实现(不过它的本质还是指针来实现,只是我们只用引用再不用去考虑指针的细节了)
代码版本二:
#include <iostream>( p! Q- h) ^: {7 \0 x
#include <string>
3 L" ^5 {, A: s3 T5 ]9 Z8 @using namespace std;/ \9 `" x3 \' u/ f/ \: a

( W! \+ i+ _# a3 @9 W/ H1 {6 M# ?- q  b* K& `2 t1 x
void Swap(int& a , int& b )//const int * a ,const int * b '
; a6 z8 C) U! n/ _3 V{
' s0 a5 l, ^) g$ R! I    int c =a;
0 v) ?9 H+ P) Z3 A    a=b;
! ]9 V7 Z! S! h7 V+ v0 P3 E    b=c;
3 |. t/ s1 w: \0 x, f}
3 [/ ^9 j0 o) s4 @/ yvoid Swap(double& a,double& b)+ u) ^9 T" j6 K' z/ k
{& E2 y, A7 Y. ^; D
    double c =a;
1 }2 Z6 S" T- T3 Y+ |    a=b;
6 X+ w; C& v# e    b=c;
5 P8 C5 ?8 e$ e( R  p; }6 _}6 b3 D/ k2 |; z4 U+ A
: ]& K, R( }, T) U  W
void Swap( string& a, string& b)
) U+ p5 I. u' v{% O# g% W, X$ Q
    string c =a;
9 s( S7 f/ S* C) n% F    a=b;7 G7 s" z$ I% R4 U8 `
    b=c;' ]; y3 U+ |3 V0 B6 v
}) u9 \& C) b, g$ \
int main()0 q! g; c& {: ]8 D
{( C& m0 z4 v6 G- G
  int a =2;
1 J; l' H1 I% d' \2 W  int b =5;7 F; ^2 {4 H! Y: y+ `
" T( }$ M/ D  z+ N; e9 M" P* x
  Swap(a,b);4 M, u5 U0 r) |1 c
  cout<<"a= "<<a<<endl;
1 f  G1 \& s5 U5 e* M  cout<<"b= "<<b<<endl;+ x7 N6 t1 R5 M" P# P* n3 Y  Q- k  s
- q/ k; B0 U! Z- n. h0 T! M
  double m =4;
' _; q2 v; r0 z& a0 Y% i  double n =6;! n5 I4 I, T  \8 q
  cout<<"m= "<<m<<endl;$ h. h2 X' [1 ]- L$ e
  cout<<"n= "<<n<<endl;/ I. P5 Q2 `, D6 f: N( J, d
6 |* N& Q0 j+ c$ U1 Q& O3 _
  string d = "Txp";
, Q5 b/ i. S% [2 E- q  string t = "xiaoping";3 W, a5 k! u2 ~5 U- Y
  ?# r+ x5 m4 G  L, ^2 v
  cout<<"d= "<<d<<endl;! T" D0 ~8 S7 O
  cout<<"t= "<<t<<endl;9 M, b1 f1 Y8 }  t  M$ U5 |

9 E' _# E( g  E  return 0;! `  Q- y; W* n2 k# [) r# k! ~
}( F6 G9 g' f/ L  y2 Q8 P2 M2 w
( i7 C. R3 \% Q8 R; D
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out
( K* t3 p# F- @/ _) U0 sa= 5( _' E; a+ D0 I. O; f/ {
b= 2! C+ B6 ^5 d/ x# s- I7 H
m= 4' z2 ]0 q; Y8 X5 r# }  S
n= 6) u1 o" h3 ^6 }& m6 B6 K! P
d= Txp
- {: R9 q3 v% |( k8 jt= xiaoping
  y: i, L- o: e3 V/ i4 n4 B/ L( R( Y5 k9 Z  U/ B
注解:同样实现了交换功能。
2、两种方法的优缺点:
定义宏代码块
-优点:代码复用,适合所有的类型
-缺点:编译器不知道宏的存在,缺少类型检查
定义函数
-优点:真正的函数调用,编译器对类型进行检查
-缺点:根据类型重复定义函数,无法diam复用,从上面的试验结果可以看出,我们每次都对Swap()函数进行重新定义,定参数的类型不一致的时候
二、泛型编程闪亮出场:
1、泛型编程的概念:
不考虑具体数据类型的编程方式,我们可以继续拿我们刚才的那个Swap函数进行改造,改成我们现在的泛型写过:
void Swap(T& a, T& b)
0 @( ]4 ]- `9 C4 D{% \' l6 [+ F2 N' J
     T t =a;
- @8 a% B, v+ Y) R8 ^7 l3 {4 n* q4 U     a =b;; x" |* r1 n% S6 k
     b =t;. \2 k$ t; k) z. [" \) c5 }1 n
}, c9 k. b, G- `% m9 V9 Q6 R# r
注解:Swap泛型写法中的T不是一个具体的数据类型,而是泛指任意的数据类型,这一点非常重要,明显有了很大提升。
2、C++中泛型编程
(1)函数模板:
  • -一种特殊的函数可用不同类型进行调用
  • -看起来和普通函数很相似,区别是类型可以被参数化

      j1 `, S% v4 \; g
template<typename T>' j' j4 I- l! g, B9 b. n$ q( G
void Swap(T& a, T& b)
* U- ^* J$ z& T5 I2 O2 V" x- }{- }: M  R3 w# `8 S) |- A% m; c
   T t = a;1 x9 \4 o$ k8 j% G/ d2 O
   a = b;
0 B& R" n% T  m% Y# S# w   b = t;
! m7 Z, n5 Z, P, s' P1 e}; f$ F+ W; D1 y* A9 ]
(2)函数模板的语法规则:
  • template关键字用于声明开始进行泛型编程
  • template关键字用于声明泛指类型
    % s9 z2 M9 K7 s' n
微信图片_20200823222407.png
(3)函数模板的使用
  • 自动类型推导调用
  • 具体类型显示调用
    ( W6 V+ d2 S" h, E
int a = 0;: u+ s; s; `0 c4 m5 ?+ r5 v% R
int b =1;  s" ^0 [# [, ?9 @3 Z
Swap(a,b)//这里属于自动推导
( h& F/ ]" v. B& z/ w+ Z
2 t/ s/ C8 C, C0 \. ~float c =2;, C' z( k! {: `
float d =6;( F9 H- \4 x& ?+ b, U1 ^$ H
+ [3 }9 f# f4 M7 o/ h6 v
Swap<float>(c,d);//这里属于显示调用
4 M: ], j6 Y( }' _% {3 y
代码实践:
#include <iostream>
3 [+ p8 w$ _/ h* @. x( P. @#include <string>$ [! t( s( v3 y7 {' V( W9 V
using namespace std;
3 P$ }( ~5 }- O( a1 M2 A; xtemplate < typename T >// 开始泛型编程,泛指类型是 T;在下面函数定义中用 T 可以代表类型;
. K: Z7 r# S1 _7 n7 yvoid Swap(T& a, T& b); W3 L  q5 K7 p+ \" ^
{. ~: q$ ^6 {) i% B) c1 a9 W" g
    T c =a;
  X) w& @, x; K# Y. V1 a    a=b;9 o7 A% O4 ?% ~6 ?, ^& T' |
    b=c;- T9 U9 W8 L4 Q; W7 H) J6 l! x
}
) H7 q& {1 s+ o# s2 k! K+ x5 |6 ]! P! ?6 N/ P0 R
template < typename T >
6 K8 b# [& e' I( D! Ivoid Sort(T a[], int len)9 h7 w6 [( Q+ t! j  p# l
{
+ N& T0 c3 @- q) @+ J- ?0 ~5 Q   for(int i=0;i<len;i++)
8 ~) f4 f* D2 g3 G1 J  k" j   {+ [4 w2 G5 |) x( p6 o1 U6 F* j5 T
      for(int j=i;j<len;j++)& x; E6 G$ u5 e/ a) A9 C
      {, P4 {3 R8 S+ ^( d1 H
         if(a > a[j])
0 z* v, J% \3 \; b  O1 \# l0 `         {5 B8 U4 t) n+ ?0 p
             Swap(a,a[j]);
* s6 S$ N# J) \, z3 |. t         }" C) z! e' e; o1 O$ `/ q
      }! H2 Q  z8 z  T$ K
   }
5 m3 O6 X* w2 D: _# h3 [) y# ?$ r6 E) J9 T8 C5 Z
}( ]* V( Z3 ^3 D) ?+ Y* y
+ u6 r' T( u# k" S' d  i7 v
. m. N% P  ]3 k3 ]. k  \; _
template < typename T >
( K* o" X+ A  f# V/ pvoid Println(T a[], int len): U* ^" v+ Q4 @3 \7 B( b
{- g$ }# z( M6 v/ I4 i
      for(int i=0;i<len;i++)7 D; e$ G* J4 v; O0 v
      {8 Z0 s, W" D, N8 E$ Y. D  }2 B
           cout<<a<<",";1 o! Q; o7 ?% A7 ~
      }& V9 U0 k- K& v5 H
      cout<<endl;" A. k; g2 z5 w
}* ]7 D) L& z$ `+ j9 G& n/ l
* S. c2 P! D. j2 H5 V/ y8 k
int main()- H$ z$ S; A( d9 a, G! L" d; [: N
{/ U# Q5 Q! i' e  a7 D1 G1 J% S

5 X6 ?' `8 ]# `$ l  int a=3;
4 V( _6 j( g. _1 o2 w' `# S( v   int b=5;1 D: r, H  s' r5 u. Z  r

3 x" ^  T" T+ ^0 d9 q* \   Swap(a,b);//自动推导,等价于 Swap<int>(a, b);
2 d" J/ o% g" P  w6 w   cout<<"a= "<<a<<endl;0 J, a1 K$ s( X3 }
   cout<<"b= "<<b<<endl;
; j5 V% T. s% f& v4 v- j
* C5 J, Y( j8 [- o+ l. V3 z1 Z   double m =4;
# t& E* v6 t  W% |, U* f% |   double n=6;! N$ X9 q/ E8 K; q- e9 u
3 u* S9 f, A9 U  o2 p
   Swap(m,n);
9 O+ }- A% H# H. F   cout<<"m= "<<m<<endl;
7 @; U! P6 h6 q: l9 B3 K4 V0 U   cout<<"n= "<<n<<endl;" r( M. ^1 E8 J3 `$ ]! i
5 ?& V% c  W: o* O* e
, q) K7 k8 F: y: L8 j0 e6 q& c
   string d = "Txp";
0 F5 W( O! |6 Z0 E: m   string t ="xiaoping";
- J' K& O- i& Y+ m. |6 J+ p
; C; E7 {+ V5 U: k0 E+ U   Swap<string>(d,t);//显示指定;将 T 替换成 string,然后进行调用;
* d' @" a  H- H! T) }   cout<<"d= "<<d<<endl;+ o: A2 D2 v+ c$ X* }$ W
   cout<<"t= "<<t<<endl;
+ M% P* j3 p2 g2 v& I: L- e
/ i5 s+ r. r" |4 r! ?8 ^
0 H5 j7 M2 V: Q% T$ M0 u; w
% M6 J, e! f$ `5 C
8 {( R( n. x9 D6 D6 W     /* 以下是选择排序算法测试代码 */
6 C: X1 {, B/ p  d3 e- V9 r/ r   int array[5]={3,5,6,4,9};# K" e" z- I$ @6 M. h) m. \  d* W
   Println(array,5);
  o, M7 \, u* h" S! ?( {2 y   Sort(array,5);
& {5 p% ~  F* Q6 ^! q7 \! j5 a. z   Println(array,5);
4 Y4 `2 H% |6 y5 O/ c
$ Z" g; o0 Q) C! |* p% Q   string s[5]={"c","c++","rust","golang","python"};
( U& F" ^# B& n$ O: C2 v" P! U( q% ]0 I; X. r& U9 O& C( Y
   Println(s,5);/ S# M: F8 }8 D1 d! L% a: ]3 b
   Sort(s,5);$ N$ j* t+ M% T$ Q6 I8 w8 f
   Println(s,5);" ]+ j8 k# M8 l' ~: W( E3 T- n
9 I# ~; \; {* L; A- {4 w0 P

" {, x" _. {* H' t6 t" J
( o; R% w$ Y9 ]9 o7 ], }& g   return 0;3 }& T1 y) M  j3 b
}5 M5 c8 Q2 a" u4 g$ h# Y1 d

; \' f, g8 r" b6 l' J, ^1 E5 P+ H9 h3 v% T4 G+ `: _
输出结果:
vroot@txp-virtual-machine:/home/txp# ./a.out
0 K8 O: V2 o8 ]: C$ X7 j& Za= 5
! W( R: g/ w! T" L3 p& r: ob= 38 m2 k8 u3 I. P& R  \
m= 6
, ?1 l4 n  q  p! dn= 4+ ]- R( H, s! t  F
d= xiaoping* o0 S9 @; n& x- o" Z' Y/ s
t= Txp
7 m6 I, G" m1 n3,5,6,4,9,1 a& z3 }, U6 f2 U# ~' p
3,4,5,6,9,; K4 X- R' g& g0 ^$ G4 ]( h
c,c++,rust,golang,python,
" I+ C$ [  g/ Z  B) Q$ ?c,c++,golang,python,rust,: w4 R* Q  d1 p2 ?$ {& N

) s" t, [4 }' G/ P3 Y' W
三、总结:
  • 函数模板是泛型编程在c++中的应用方式之一
  • 函数模板能够根据实参对参数类型进行推导
  • 函数模板支持显示的指定参数类型
  • 函数模板是C++中重要的代码复用方式
    4 R: j6 X. G- i
好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。

' o' S2 t: V0 }) W! S* C) V4 Y
赞 收藏 评论0 发布时间:2020-8-23 22:24

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版