C++函式模板&類模板

文章目錄
- C++函式模板&類模板
- 一、函式模板
- 1.函式模板的定義
- 2.函式模板的實體化
- 3.函式模板的多載
- 4.函式模板和函式的次序
- 5.函式模板示例:Map
- 二、類模板
- 1.類模板的定義
- 2.函式模版作為類模板成員
- 3.類模板與非型別引數
- 4.類模板與派生
- 5.類模板與友元
- 6.類模板與靜態成員變數
一、函式模板
1.函式模板的定義
template <class 型別引數1,class 型別引數2,……>
回傳值型別 模板名 (形參表) {
函式體
};
2.函式模板的實體化
-
通過引數實體化:
-
交換兩個變數函式模板:
template <class T> void Swap(T &x, T &y) { T tmp = x; x = y; y = tmp; } int main() { int n = 1, m = 2; Swap(n, m); //編譯器自動生成 void Swap(int & ,int & )函式 double f = 1.2, g = 2.3; Swap(f, g); //編譯器自動生成 void Swap(int & ,int & )函式 return 0; } -
編譯器自動生成 void Swap(int & ,int & )函式
void Swap(int &x, int &y) { int tmp = x; x = y; y = tmp; } -
編譯器自動生成 void Swap(int & ,int & )函式
void Swap(double &x, double &y) { double tmp = x; x = y; y = tmp; }
-
-
不通過引數實體化:
直接呼叫函式名<型別引數串列>(引數串列)#include <iostream> using namespace std; template <class T> T Inc(T n) { return 1 + n; } int main() { cout << Inc<double>(4) / 2; //輸出 2.5 return 0; }
3.函式模板的多載
函式模板可以多載,只要它們的形參表或型別引數表不同即可,
template <class T1, class T2>
void print(T1 arg1, T2 arg2)
{
cout << arg1 << " " << arg2 << endl;
}
template <class T>
void print(T arg1, T arg2)
{
cout << arg1 << " " << arg2 << endl;
}
template <class T, class T2>
void print(T arg1, T arg2)
{
cout << arg1 << " " << arg2 << endl;
}
4.函式模板和函式的次序
在有多個函式和函式模板名字相同的情況下,編譯器如下處理一條函式呼叫陳述句:(匹配模板函式時,不進行型別自動轉換)
-
- 先找引數完全匹配的普通函式(非由模板實體化而得的函式),
-
- 再找引數完全匹配的模板函式,
-
- 再找實引數經過自動型別轉換后能夠匹配的普通函式,
-
- 上面的都找不到,則報錯,
5.函式模板示例:Map
-
代碼:
#include <iostream> using namespace std; template <class T, class Pred> void Map(T s, T e, T x, Pred op) { for (; s != e; ++s, ++x) { *x = op(*s); } } int Cube(int x) { return x * x * x; } double Square(double x) { return x * x; } int a[5] = {1, 2, 3, 4, 5}, b[5]; double d[5] = {1.1, 2.1, 3.1, 4.1, 5.1}, c[5]; int main() { Map(a, a + 5, b, Square); for (int i = 0; i < 5; ++i) cout << b[i] << ","; cout << endl; Map(a, a + 5, b, Cube); for (int i = 0; i < 5; ++i) cout << b[i] << ","; cout << endl; Map(d, d + 5, c, Square); for (int i = 0; i < 5; ++i) cout << c[i] << ","; cout << endl; return 0; } -
輸出:
1,4,9,16,25,
1,8,27,64,125,
1.21,4.41,9.61,16.81,26.01, -
實體化:
Map(a, a + 5, b, Square); //實體化出以下函式: void Map(int *s, int *e, int *x, double (*op)(double)) { for (; s != e; ++s, ++x) { *x = op(*s); } }
二、類模板
1.類模板的定義
-
類模板:
在定義類的時候,加上一個/多個型別引數,在使用類模板時,指定型別引數應該如何替換成具體型別,編譯器據此生成相應的模板類,
-
模板類的寫法:
template <class 型別引數1,class 型別引數2,……> //型別引數表 class 類模板名 { 成員函式和成員變數 }; -
類模板里成員函式的寫法:
template <class 型別引數1,class 型別引數2,……> //型別引數表 回傳值型別 類模板名<型別引數名串列>::成員函式名(引數表) { …… } -
用類模板定義物件的寫法:
編譯器由類模板生成類的程序叫類模板的實體化,由類模板實體化得到的類,叫模板類,類模板名 <真實型別引數表> 物件名(建構式實參表);-
同一個類模板的兩個模板類是不兼容的:
Pair<string,int> * p; Pair<string,double> a; p = & a; //wrong
-
-
類模板示例: Pair類模板:
template <class T1, class T2> class Pair { public: T1 key; //關鍵字 T2 value; //值 Pair(T1 k, T2 v) : key(k), value(v){}; bool operator<(const Pair<T1, T2> &p) const; }; template <class T1, class T2> bool Pair<T1, T2>::operator<(const Pair<T1, T2> &p) const //Pair的成員函式 operator < { return key < p.key; } int main() { Pair<string, int> student("Tom", 19); //實體化出一個類 Pair<string,int> cout << student.key << " " << student.value; return 0; }輸出:
Tom 19
2.函式模版作為類模板成員
#include <iostream>
using namespace std;
template <class T>
class A
{
public:
template <class T2>
void Func(T2 t) { cout << t; } //成員函式模板
};
int main()
{
A<int> a;
a.Func('K'); //成員函式模板 Func被實體化
a.Func("hello"); //成員函式模板 Func再次被實體化
return 0;
}
輸出:KHello
3.類模板與非型別引數
-
類模板的“<型別引數表>”中可以出現非型別引數:
template <class T, int size> class CArray { T array[size]; public: void Print() { for (int i = 0; i < size; ++i) cout << array[i] << endl; } }; CArray<double, 40> a2; CArray<int, 50> a3; //a2和a3屬于不同的類
4.類模板與派生
-
類模板從類模板派生
-
基類A:
template <class T1, class T2> class A { T1 v1; T2 v2; }; -
派生類B:
template <class T1, class T2> class B : public A<T2, T1> { T1 v3; T2 v4; }; -
B<int,double> obj1;的實體化class B<int,double>: public A<double,int> { int v3; double v4; };class A<double, int> { double v1; int v2; };
-
-
類模板從模板類派生
template <class T1, class T2> class A { T1 v1; T2 v2; }; template <class T> class B : public A<int, double> { T v; }; int main() { B<char> obj1; //自動生成兩個模板類:A<int,double> 和 B<char> return 0; } -
類模板從普通類派生
class A { int v1; }; template <class T> class B : public A { //所有從B實體化得到的類,都以A為基類 T v; }; int main() { B<char> obj1; return 0; } -
普通類從模板類派生
template <class T> class A { T v1; int n; }; class B : public A<int> { double v; }; int main() { B obj1; return 0; }
5.類模板與友元
-
函式、類、類的成員函式作為類模板的友元
void Func1() {} class A { }; class B { public: void Func() {} }; template <class T> class Tmpl { friend void Func1(); friend class A; friend void B::Func(); }; //任何從Tmp1實體化來的類,都有以上三個友元 -
函式模板作為類模板的友元
任意從
template <class T1,class T2>
ostream & operator<< (ostream & o,const Pair<T1,T2> & p)
生成的函式,都是任意Pair摸板類的友元#include <iostream> #include <string> using namespace std; template <class T1, class T2> class Pair { private: T1 key; //關鍵字 T2 value; //值 public: Pair(T1 k, T2 v) : key(k), value(v){}; bool operator<(const Pair<T1, T2> &p) const; template <class T3, class T4> friend ostream &operator<<(ostream &o, const Pair<T3, T4> &p); }; template <class T1, class T2> bool Pair<T1, T2>::operator<(const Pair<T1, T2> &p) const { //"小"的意思就是關鍵字小 return key < p.key; } template <class T1, class T2> ostream &operator<<(ostream &o, const Pair<T1, T2> &p) { o << "(" << p.key << "," << p.value << ")"; return o; } int main() { Pair<string, int> student("Tom", 29); Pair<int, double> obj(12, 3.14); cout << student << " " << obj; return 0; }輸出:
(Tom,29) (12,3.14) -
函式模板作為類的友元
所有從template <class T>
void Print(const T & p)
生成的函式,都成為 A 的友元
但是自己寫的函式
void Print(int a) { }
不會成為A的友元#include <iostream> using namespace std; class A { int v; public: A(int n) : v(n) {} template <class T> friend void Print(const T &p); }; template <class T> void Print(const T &p) { cout << p.v; } int main() { A a(4); Print(a); return 0; }
輸出:
4
-
類模板作為類模板的友元
A< double>類,成了B<int>類的友元,
任何從A模版實體化出來的類,都是任何B實體化出來的類的友元#include <iostream> using namespace std; template <class T> class B { T v; public: B(T n) : v(n) {} template <class T2> friend class A; }; template <class T> class A { public: void Func() { B<int> o(10); cout << o.v << endl; } }; int main() { A<double> a; a.Func(); return 0; }輸出:
10
6.類模板與靜態成員變數
類模板中可以定義靜態成員,那么從該類模板實體化得到的所有類,都包含同樣的靜態成員,
#include <iostream>
using namespace std;
template <class T>
class A
{
private:
static int count;
public:
A() { count++; }
~A() { count--; };
A(A &) { count++; }
static void PrintCount() { cout << count << endl; }
};
template <>
int A<int>::count = 0;
template <>
int A<double>::count = 0;
int main()
{
A<int> ia;
A<double> da;
ia.PrintCount();
da.PrintCount();
return 0;
}
輸出:
1
1
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/258776.html
標籤:其他
