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

C++——类模板的深入学习

[复制链接]
gaosmile 发布时间:2020-8-26 22:22
一、类模板的深入学习:
1、类模板可以定义任意多个不同的类型参数(这一点和模板函数一样)
template < typename T1, typenaem T2 >! ~+ t* _( z) Q3 ^% `$ p8 z/ M, ~
class Test
9 X" H9 F* i% e* i{
8 S: h  ]4 ^' wpublic:
2 H8 q% \, [# h# k6 W+ ~    void add(T1 a, T2 b);
: b$ g7 j, u3 @; S0 C& l7 a: w}
* I3 y: Z# v3 H7 z) i& H$ z
) S/ D3 B5 D% _0 N. X- R//定义类对象时
0 P; W1 U" Y9 G. c; TTest<int,float> t;" |; p  k& L' H$ x, G7 [9 i( y
2、类模板可以被特化
  • 指定类模板的特定实现
  • 部分类参数必须显示指定
  • 根据类型参数分开实现类模板
    $ _- h& x# E( s: m% |4 [. l
特化前:
template < typename T1, typename T2 >
8 S  e( A" r5 B6 gclass Test
' ]& x: G1 X6 [" v3 C: e{8 s) z$ `" x0 c' E
   
( P% j9 q, G) h% S};
+ {( E$ y8 Y  Z  g0 q; U0 U" I( a, B
特化后:
template < typename T >! L- W$ }3 v; e3 @0 [
class Test < T , T >
1 e5 e+ e5 t5 B8 C: c3 P{1 y- T  \4 b5 q' m$ `. U
  @1 G+ Z' n2 c
};
  B  _8 F; o# ]8 [. O' m
3、类模板的特化类型:
  • 部分特化:用特定的规则约束类型参数
  • 完全特化:完全显示指定类型参数
    9 I; o8 U, T, u% j+ H
完全特化前:
template <typename T1, typename T2 >  O/ v, Q! |2 t! C' j
class Test
: X1 n/ L" t) r- [) L{+ k% t3 r0 c( o% `. z' Z
) Y! H  {, |* u7 c% S
};' S$ G+ t: p3 y, J: T. _9 l
完全特化后:
template < >4 R7 g4 U: r, z/ W  E" U1 s$ T! s2 Q
class Test < int, int>
2 d7 Y# G8 v. ]& K{
4 y) q$ ~$ }. c% T; L4 T( _$ p# ]* x5 }" Y) i' q/ P# R( h

1 C- L( Y9 ]; n};
8 i! n4 {5 _+ I: X4 C- Y+ h5 A: ]
代码实践:
#include <iostream>3 P, _' d) U5 L! t9 _$ K3 D
#include <string>
% R3 T3 g: K% Z+ G1 h/ J6 z+ I$ S2 b. m# _' C
using namespace std;
" p6 t- U- D* J) z$ c
6 R/ M9 h9 U0 v$ Ftemplate < typename T1, typename T2 >- D8 f% Z5 ~. {1 q& f/ h
class Test
& @4 j0 M+ E7 R" ~9 M5 @{
$ l% u. |5 r! b0 w$ Q. Hpublic:
4 \2 x% ^+ k# Q; C* f   void add(T1 a, T2 b)$ p- x! e( N* E( `) Y0 m5 f& d
   {
+ _- B; T1 F! a  w8 k8 \% N       cout<<"void add(T1 a, T2 b)"<<endl;
) K- q8 m) J) S. |* @0 {       cout<<a+b<<endl;
% j  `7 b- g& l, A4 ~   }
9 R! w5 \  E" W( N' [};7 t) T! B, {, S& V5 {' @
* h9 J4 c* o" u0 _
/* 关于上述第一个类模板的特殊实现,关于指针的特化实现 */
( _1 J' q% k* J( O( T  Utemplate < typename T1 , typename T2 >- |! }* p3 t- i/ P- `
class Test < T1*, T2* >
3 M# f/ C9 g2 Z5 }9 p: k{
6 d# a7 ^- e/ h4 m2 b" b0 Zpublic:
8 C, Q' \6 @* Z3 c    void add(T1* a, T2* b)) x" p3 ^: O' h  u8 ]/ ?8 T) Q* g' E
    {% H: P' u  i5 {% E
       cout<<"void add(T1* a, T2* b)"<<endl;0 L8 L4 P: ]1 c/ S0 F) I  [$ o
       cout<<*a+*b<<endl;. y+ R' j2 H* Q! ^" M5 |
    }
2 A+ g- ^9 N* i( W) h
6 a8 L! a2 C  F' \};
$ V% q) c* E; }+ o8 \( |7 M; D8 Y% @9 @1 L/ m3 {& z" _. M
template < typename T >//特化' u( P' [$ H4 u
class Test  <T ,T  ># ~+ j" R4 h6 C
{
6 M$ Z& h* N7 Cpublic:
' d/ N3 b( B* u' ]3 [' R& w4 n   void add(T a, T b)! W3 A/ \0 U: Q# k5 }( x
   {
4 [$ M9 B' z* }) Q6 v4 J" J8 |0 v         cout<<"void add(T a, T b)"<<endl;
' i' D2 W5 k; P: _, q8 O9 a$ V         cout<<a+b<<endl;/ s7 i$ V0 l) A, `( v1 d/ C9 P
   }9 ~+ W) J) y8 v3 L4 a2 s
   void print()
6 `( y7 G* R' x  o3 l3 O$ }: r   {
2 J" O% r( P! @; d: \0 W0 g$ }) v. O4 v" ?8 p
     cout<<"class Test  < T , T >"<<endl;& R" Y% h6 r- O
   }2 e- N3 D# q' f4 V; i
};
& o/ S% a- y4 s/ _/ M
5 h5 i0 {& p/ r$ y9 Q7 ]9 X8 ltemplate < >//完全特化9 C6 t, V+ R+ J
class Test < void * , void * >
: ~. N2 }3 m2 ~{. c% r# i/ g" X1 V6 h" w+ ?% V: {
public:( J# ^4 {+ c, {4 g1 I" J
   void add(void* a, void* b); ?- e1 u7 {/ h! S
   {
) u* m2 n% A+ c* {      cout<<"void add(void* a, void* b)"<<endl;( F, ^; n5 |& h' {5 h2 P
      cout<<"error to add void* parm"<<endl;
5 [5 V$ \  I" E$ \8 J0 ^* ]: u    }( `( G7 E& B8 u, e4 u# N6 W
};* q/ n9 b7 S9 Z: g# X
/ s$ e' n) d' _. Y% n
int main(), z0 i) v( p8 q0 b- c% e
{
# B8 a) c3 L7 j5 R! m    Test<int, float> t1;5 U/ y0 {7 N, X6 N) N2 ~
    Test<long, long> t2;
/ m! r5 o4 ^: G' @; ~3 C    Test<void*, void*> t3;. ?) f. s8 B* `; A- W2 G' n, t
" V  [- L! o2 |! Y2 b$ N
    t1.add(1,2.5);; B; D! o: E& B6 \7 E# B1 ^" m6 A
    t2.add(5,5);
) R  |: f- l- b* e" f    t2.print();
+ B, B3 g1 Q1 S% j: b/ V6 `- x; V
" I3 e+ w) k6 [# F, Q% D    t3.add(NULL,NULL);
+ q+ `' N# p3 {& P( O& B
# W& ~: }, x  B& P    Test< int* , double* > t4;
7 y' L2 i' c, E3 s    int a =1;
& ]0 V. Y( \/ ]2 K7 B9 Y8 n    double b = 0.1;
& Z; s' W; ^5 t0 ]
9 a' j1 b# A9 Y3 W) G% d2 O    t4.add(&a,&b);) e7 }1 Q: O$ `2 G3 S/ j3 E
   return 0;7 j& d/ C. G2 X- O; H; q6 i; D' {
}$ G7 T1 L# J# O; t& ~

1 l9 q) H1 p7 @( G% W8 N
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out
% c  J# X1 Y0 ^- }- gvoid add(T1 a, T2 b)
4 u: E4 g+ f, x3.5+ o$ ~% L- _9 o5 l- `
void add(T a, T b)
! N% r1 l5 F7 r100 z/ e) I4 l4 c% F2 ~
class Test  < T , T >
( k7 |* D7 Y8 E- O6 |9 o8 H+ E* |0 Gvoid add(void* a, void* b)
# E% F7 D/ C. s3 H' I! Cerror to add void* parm- }$ p% N- ^( _. p4 y( h7 j1 \9 P
void add(T1* a, T2* b)
! V* C! W. y" W+ M1.19 _! B5 o( t. j* [. T5 m

1 D5 w' I6 u" y% \6 z; V2 t+ k
4、类模板特化注意事项:
(1)特化只是模板的分开实现
本质上是同一个类模板
(2)特化类模板的使用方式是统一的
必须显示指定每一个类型参数
5、类模板特化与重定义有区别吗?函数模板可以特化吗?
(1)重定义和特化的不同:
重定义:
--一个类模板和一个新类(或者两个类模板)
--使用的时候需要考虑如何选择的问题
特化:
--以统一的方式类使用类模板的特化类
--编译器自动优先选择特化类
(2)函数模板只支持参数完全特化
函数模板特化前:
template < typename T >
  J8 D) G, x8 w# n# L, T9 E% C! B: G0 R0 P% N4 x6 H
bool Equal(T a, T b)
% I1 T) r- f+ o; }* a- g- s{+ h! Q4 v/ ~1 }' r, c  M" U
   return a==b;
7 P+ `8 e/ ]$ A+ }, G" w}# ~8 h9 a2 K' t0 O8 X$ ]
函数模板完全特化后:
template < >* {  `( S, F2 q! w2 Z
bool Euqal<void*>(void* a, void* b)& m: {9 n5 ^  ^
{
; [; y7 }; r3 V) g$ I7 [     return a==b;
6 r1 v. G, e6 s, G# C. ~}
" d9 O7 e% D" M
代码实践:
#include <iostream>
: m1 F2 L! o6 w. r. _2 p#include <string>
1 p1 `- C5 f1 u6 q& {( U  V+ }  V* _8 X0 J, H
using namespace std;
4 o) F+ y! ]% }0 ?+ o- R
' q6 c3 n# R& G. G* dtemplate7 K) a% \/ f+ y1 l+ `7 Q3 _
< typename T1, typename T2 >9 V% _2 q8 ~# J" q# d, z
class Test
5 y5 n2 j' y( H{
9 p% \6 i' U$ V. R$ h) Jpublic:$ v" ]' c/ n0 i: e- K* S  V
    void add(T1 a, T2 b)7 O1 a* C) j5 \1 a9 S8 M
    {
) [; ^7 E3 |2 E' z8 D; k3 v8 ^- \        cout << "void add(T1 a, T2 b)" << endl;
/ j* G$ s, Y  _* k" M        cout << a + b << endl;
3 k& ]8 ^. \; |: N- j& z    }+ b5 S5 K1 y3 [
};
0 y; H# a& ~! {2 W8 J7 Q
% I# Z- b0 Y$ A1 ?: a6 f4 @: h/*
( g( R* X: q9 l; o( h" D1 _5 Ytemplate% T* o* z, E% X9 O( {& R+ f
<  >. N# X  ~+ Q+ m# e0 K& f2 V- r) N
class Test < void*, void* >    // 当 T1 == void* 并且 T2 == void* 时
, u; T/ q/ c' J  w{
5 _& u  a$ _. |& qpublic:
" z" V3 X; r" [/ o8 J8 D    void add(void* a, void* b)8 a7 V& _4 p# u& ^8 Y3 W
    {, k  f4 ?3 G- \8 }2 u# Z
        cout << "void add(void* a, void* b)" << endl;- C2 E" P) {' d) G
        cout << "Error to add void* param..." << endl;: ^8 t+ v( b$ ]1 ]9 p7 b# Z* H
    }
5 z1 Q" a2 A( }6 v};
$ j; a; S$ c: f- Q*/1 b5 R! d1 M, w; a2 P1 _
. N/ i2 Y1 f7 i0 C
class Test_Void. R% P9 @# A, {( ?2 a; ?+ F
{7 X$ B/ U0 |5 P! Y1 a8 I5 O" h5 P: @
public:
0 r4 v# M5 n: f* V: ~7 s% m% _% O3 C- I( z    void add(void* a, void* b)
0 d" b+ w8 R/ C# Q    {! u% O: r, K& K( n# A/ J
        cout << "void add(void* a, void* b)" << endl;) ~( o; T1 b/ p: J
        cout << "Error to add void* param..." << endl;4 D! |& ~! R& t. Y
    }
3 s$ T0 {+ Z3 t' W2 q- n* d};' z; W; B* W, g7 F
  P0 i* U& L! `  H) Q5 u
template
% N5 U  V$ X; l% ~9 n8 [< typename T >
8 U+ H- l; I( u* B9 ?bool Equal(T a, T b)' x" p/ ]9 l! s7 [6 T
{
, t; @/ ~- K3 P" K: X* ?3 A2 B+ ^5 f6 k    cout << "bool Equal(T a, T b)" << endl;! R: ^/ A1 L# j- P- K1 f7 T! w0 }
    " m6 G5 `0 _: L4 e
    return a == b;
+ I* h3 E- D" F  [}
5 d/ Y0 Q0 {2 J9 ]1 o
: ]8 k) u7 D: P7 f3 o4 ?template! g1 W. S* i4 u
< >" h7 x, G, V6 R# y6 D' G
bool Equal<double>(double a, double b)+ F; H& W7 p; S0 b, M
{
; C) q# P/ [, {. O8 l0 K: x0 G, ]    const double delta = 0.00000000000001;0 [6 ]: \, c$ i( V4 c8 C4 w6 n0 z0 r
    double r = a - b;8 n  w7 ^3 [8 x4 N
   
, J6 h) |8 }8 R0 E3 v    cout << "bool Equal<double>(double a, double b)" << endl;
* e( k9 q, e0 e9 G+ z- z    9 a# l0 A1 ~5 h3 R* S5 p7 F- r
    return (-delta < r) && (r < delta);: D+ s7 o" L! N8 w
}' t5 U. C/ A" p* R  E9 m" W% S0 v6 _

+ ^; K8 W0 h5 ~* pbool Equal(double a, double b)
7 K! y+ c+ Z5 K& z2 r/ Z% h{
. w) i, ?5 v2 W! I( Y7 h    const double delta = 0.00000000000001;
4 E0 N+ S0 C0 Z* j3 r' x    double r = a - b;
0 a( \% B# Y% u) h( |   
5 I; z# [& N. N8 @, Q    cout << "bool Equal(double a, double b)" << endl;# e$ d) N9 ?/ `; B0 J" M; k
   
) V" l! s  T( ~, q/ x6 ?" c5 A% }8 T    return (-delta < r) && (r < delta);
% @8 ]* G$ B0 ^4 e9 R) ~: `}  C  d  l9 y& z- r9 w9 w3 @/ O

5 s% O  |& g) M& \7 V1 g7 |int main()
) c+ n4 o1 [9 Q7 S{  
" }7 L. X. s3 f* @$ _6 V. _    cout << Equal( 1, 1 ) << endl;
. x# }; J( B) i" F    cout << Equal<>( 0.001, 0.001 ) << endl;
4 C4 d# K* q0 ]  x; g5 r; a  e    0 E; X, a/ Q4 f# [: d* U5 x
    return 0;
) l5 ]) H" \, x, ~}
- Q, J: u) n! B) J! r- P
: b+ E1 h7 \* R- G' t9 s/ X* d# @9 t: V
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out
9 l! Y- {" Y+ _( Ibool Equal(T a, T b)
5 H7 z2 d, v1 s% }& B* t  ]1
3 Z1 l7 h" `: T5 _bool Equal<double>(double a, double b)
. ]! P; j$ g9 s. k3 K1
: d0 F6 j% D6 \! h1 l' x. L3 t' d# q7 E$ H, a$ s
注解:当需要重载函数模板时,优先考虑使用模板特化;当模板特化无法满足需求,再使用函数重载
二、总结:
  • 类模板可以定义任意多个不同的类型参数
  • 类模板可以被部分特化和完全特化
  • 特化的本质是模板的分开实现
  • 函数模板只支持完全特化
  • 工程中使用模板特化代替类(函数)重定义
    : c) T! L" {, `; O8 h  i( P
好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。

2 C7 w1 k" m( j( J3 J" ]" x
赞 收藏 评论0 发布时间:2020-8-26 22:22

举报

0个回答

所属标签

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