|
在昨天的文章里面,我们给大家简单的分享了关于c++里面的函数模板的概念,通过代码示例,我们对函数模板的优势有了一个比较清楚的认识。咋们今天继续来深入学习函数模板。以下内容是今天知识学习总结笔记。 一、函数模板的深入理解: 1、函数模板深入理解:
-对模板代码本身进行编译,比如检查函数模板是否有语法上的错误 -对参数替换后的代码进行编译;也就是说,我们在调用函数模板的时候,编译器根据实际的参数类型,从而得到真正的函数,这个时候编译器会对这个函数进行第二次编译 2、注意事项:
-自动推导类型时,必须严格匹配 -显示类型指定时,能够进行隐式类型转换 代码实践: 代码版本一: #include <iostream>#include <string>' B+ G6 r3 F- M h! r1 L) a 0 ~$ m3 f- f# n: ]3 d using namespace std; ! q0 x8 v @/ T% f! @" F: B class Test# f4 c8 L3 D3 e; A1 ] { Test(const Test&);; F) i- K" ?7 T2 _5 n public: Test() {7 O, w3 U+ E4 Y) d9 z+ J7 Y! | }' B9 | ^! Y& h$ y; U };5 }( z7 M6 j9 ~9 X3 O 1 u2 i2 O- m7 F template < typename T >& Y0 I& i U: v4 ~7 D$ u6 t0 Z void Swap(T& a, T& b)# W- p* |2 N2 g1 t# h4 N- h { T c = a;: f0 F* [7 P' |& S7 o a = b; a = c; }5 Z0 h d2 s+ x* y typedef void(fun1)(int&, int&); typedef void(fun2)(double&, double&); typedef void(fun3)(Test&,Test&); int main() {3 i0 }) B: j# x$ D/ _, u: U, Z /* p1 和 p2 指向具体函数,但是 p1 和 p2 指向的具体函数是由函数模板具体产生,这里已经产生了函数,不是模板了,这两个函数是两个独立的不同的函数,我们通过函数打印地址,就能够明显发现 */ fun1 *p1 = Swap; // 定义函数指针,并能编译通过;这里编译器通过函数指针的类型自动推导 T 为 int; 编译器默默做的事有:1、首先进行自动推导;2、产生真正的 Swap() 函数;3、将实际生成的 Swap() 函数地址用于初始化 pi;# Y2 A9 @* q: P5 H% o( w; s( }( M) d fun2 *p2 = Swap;//编译器自动推导为double ! _& j7 l5 k, s! [, C cout<<"p1 ="<<reinterpret_cast<void*>(p1)<<endl;//// 将 p1 这个指针的类型重解释为 void* cout<<"p2 ="<<reinterpret_cast<void*>(p2)<<endl; ) r8 s# V9 x9 Z. z8 t. r return 0; } 5 D( i4 g4 j& s9 c. o8 t; t 输出结果: root@txp-virtual-machine:/home/txp# ./a.out5 C. y M. b* M, W1 f- u3 Sp1 =0x4009641 J3 g0 V2 @' t2 q9 P- |) i" I3 \ p2 =0x400990 代码版本二: #include <iostream>, W; r4 O& G3 C* X#include <string>) F1 U0 b) w) f0 T c& S . M, u9 v( ~& Y2 S$ `0 { using namespace std;0 i) |! f/ |, N% c9 C ; {% y: w% `3 D& M; q* t% W class Test {5 {" r& @0 ^" X/ L; w Test(const Test&);. {& l* l4 c# a" f; [* } public:( I$ E& m0 A4 h* X5 \. c Test() {+ ]4 f* m" R1 X }$ y1 K& G% [' Q- P. q };5 o% G3 Q% V4 ^' C6 L! v# ?3 }3 j( N template < typename T >; a; ]( X3 I, L2 V$ @! P4 B void Swap(T& a, T& b)! q& U* o r% v {' w6 E/ {: x4 \0 W T c = a; a = b; a = c; }' Z# L' Z" `2 d8 c% _ D typedef void(fun1)(int&, int&);9 r" f/ C( y G4 O+ J. M5 m; r$ M typedef void(fun2)(double&, double&);& i p* G# s+ P6 F; K1 |7 k typedef void(fun3)(Test&,Test&); int main() { fun1 *p1 = Swap;( W9 Q* K m6 `) e2 g fun2 *p2 = Swap;. Y: u! d; T- d" z0 u fun3 *p3 = Swap; 6 Y" E: G3 U. E. j- `& V cout<<"p1 ="<<reinterpret_cast<void*>(p1)<<endl;/ ?: @0 B5 u$ O3 k7 m8 ] cout<<"p2 ="<<reinterpret_cast<void*>(p2)<<endl; cout<<"p3 ="<<reinterpret_cast<void*>(p3)<<endl;4 i+ a6 [6 y* `1 [5 n5 z$ z return 0;( W. X4 a# `* e4 f }6 e) b3 V' Q4 V6 R + ~- K% A+ E' [, F9 X/ ?! ?+ O 输出结果: root@txp-virtual-machine:/home/txp# g++ test.cpptest.cpp: In instantiation of ‘void Swap(T&, T&) [with T = Test]’: test.cpp:32:16: required from here( [' @/ e, R8 t$ [$ H1 O test.cpp:8:6: error: ‘Test::Test(const Test&)’ is private Test(const Test&); ^ test.cpp:19:11: error: within this context T c = a;% y5 J7 M, Q- s0 J9 f L# A7 E& @: b ^ 注解:显示编译器自动推导T为Test类,也就是Swap(T&,T&),然后就报了一个错误,说拷贝构造函数是私密的,所以也就导致Test c =a这里报错了 3、多参数函数模板 (1)函数模板可以定义任意多个不同的类型参数 template < typename T1, typename T2, typename T3 >T1 Add(T2 a, T3 b)) k; L$ N1 d1 r- g: n! _8 l { return static_cast<T1>(a+b);/ x4 A/ Y2 t2 f( K6 ^8 K4 F }( j2 u+ ?# w. R$ S (2)对于多参数函数模板
int r1 =Add<int>(0.5,0.8); //T1 = int, T2 = float, T3 = double4 b0 G J0 N) f3 ` int r2 =Add<int,float>(0.5,0.8); //T1 = int, T2 = float, T3 = float6 M# x! u1 n5 l) ` int r3 =Add<int,float,float>(0.5,0.8);, ?$ A, [$ P1 V0 _. K; `) G& X 注:工程中将返回值参数作为第一个类型参数 代码实践: #include <iostream>5 F7 O7 O; W$ D1 I, ~) q( T#include <string>* A2 z6 f( I# [ , v7 N! S- |* r using namespace std;6 r3 V$ o/ w7 r, o, H6 m template < typename T1, typename T2, typename T3 >1 J$ p$ G4 ^1 `/ j$ v* a2 Z T1 Add(T2 a, T3 b) {# S* R& x- T, T, ? i- f return static_cast<T1>(a + b); } 7 n" f/ u6 u3 M$ K int main()- B8 r& ^4 I' C. _2 ^- v {: V' c0 q1 X }5 O( h5 o. d' p // T1 = int, T2 = double, T3 = double int r1 = Add<int>(0.5, 0.8); // T1 = double, T2 = float, T3 = double: w0 o3 }8 y i4 a6 A double r2 = Add<double, float>(0.5, 0.8);; G- v2 G }: ]4 V // T1 = float, T2 = float, T3 = float float r3 = Add<float, float, float>(0.5, 0.8);6 h4 I# F/ G( _# `4 }8 C+ \) x cout << "r1 = " << r1 << endl; // r1 = 13 A/ u6 R3 n: c1 g9 i cout << "r2 = " << r2 << endl; // r2 = 1.3 cout << "r3 = " << r3 << endl; // r3 = 1.3 8 K/ k: ^- ^7 {# K3 w% W4 f7 A: q return 0;+ b( w: I# T* y& V7 \2 p/ | } # f; r2 F+ h& S Q' A: H, M 输出结果: root@txp-virtual-machine:/home/txp# ./a.outr1 = 1) ^+ q6 R2 @/ G- N r2 = 1.3 r3 = 1.3 9 }( h; a" G6 O% G% A$ k" | H 4、当函数重载遇到函数模板会发生什么? (1)函数模板可以像普通函数一样被重载
代码实践: #include <iostream>) G4 s! j Y1 H8 e* e#include <string>2 v2 k" d/ b2 D , w% k) s6 ^6 ^& h) X using namespace std; template < typename T >' T3 r3 G& s0 o. E6 ^: j) s T Max(T a, T b) { cout << "T Max(T a, T b)" << endl; $ g8 n- `! M; D! D" R return a > b ? a : b; }& h+ ]! U- T, B4 O* `4 c int Max(int a, int b)1 _# f7 l: g8 H; X; m, q {; o+ J) G" r) f0 J4 A7 n cout << "int Max(int a, int b)" << endl;6 o: w6 }/ g$ r9 |4 a + i6 F; L9 L2 g. T! B- F7 E return a > b ? a : b; }. u) N S5 e" K \! q template < typename T > T Max(T a, T b, T c)& }# x% P4 W( S! \" I2 h( f { cout << "T Max(T a, T b, T c)" << endl; 6 i% w8 `; d9 @6 G$ }8 j0 m" j return Max(Max(a, b), c); } int main(); m2 F; i, G3 u9 i, | { int a = 1; int b = 2;0 r" R6 Z% L: x2 L Y1 S- u 7 C1 i6 w* ?- u# J }5 ^- ^& G cout << Max(a, b) << endl; // 普通函数 Max(int, int) % Q6 K# }( E/ }! O* @# g. Z6 R cout << Max<>(a, b) << endl; // 函数模板 Max<int>(int, int) `( e; K% Y2 K" M cout << Max(3.0, 4.0) << endl; // 函数模板 Max<double>(double, double)5 l" @' N) B& j4 p cout << Max(5.0, 6.0, 7.0) << endl; // 函数模板 Max<double>(double, double, double)+ q, C/ Y9 ?; f6 s5 q cout << Max('a', 100) << endl; // 普通函数 Max(int, int)! F' z9 ?/ `& P1 U8 m, @ 0 k: y% X: z# o* y8 p0 h) \5 u- X return 0; }# [$ r6 V7 G. a% f( N ' e7 [* L$ [4 M" r( S9 G 输出结果: root@txp-virtual-machine:/home/txp# ./a.out) ^& H) P7 i- h, mint Max(int a, int b) 2 T Max(T a, T b)0 W/ b& z6 x! B$ E" l$ [# A+ e 2 T Max(T a, T b)) U0 f5 L6 Q {! ^% G: ` 42 z2 A5 y8 w/ k I Max(T a, T b, T c)- O+ O/ c0 p" d% h) Y$ \" n T Max(T a, T b) T Max(T a, T b) 7 int Max(int a, int b)& e" Y2 y# g8 i. i 1007 h$ ~- z/ z/ B. a9 e0 u$ Y- u ' a3 N( o3 |5 S1 N% \3 l6 f 二、总结:
好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。 |
| 学习了 |
微信公众号
手机版