日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

函数模板与类模板

發布時間:2024/1/18 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 函数模板与类模板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

函數模板:
?? ?將功能相同,類型不同的函數(類)的類型抽象成虛擬的類型。當調用函數(類實例化對象)的時候,編譯器自動將虛擬的類型 具體化
?? ?。這個就是函數模板(類模板)。目的是為了實現泛型,減少編程的工作量,增加函數的復用性
?? ?關鍵字template
?? ?注意,函數模板會編譯兩次:第一次:是對函數模板本身的編譯,第二次:函數調用外 將T的類型具體化
template<typename T>
void SwapAll(T &a,T &b)
{
? ? T temp;
? ? temp = a;
? ? a = b;
? ? b = temp;
? ? return;
}
int main()
{ ??
? ? int a, b;
? ? a = 10;
? ? b = 20;
? ? SwapAll(a,b);
? ? cout << a << " " << b << endl;
? ? char c, d;
? ? c = 'a';
? ? d = 'b';
? ? SwapAll(c, d);
? ? cout << c << " " << d << endl;
? ? return 0;
}

?? ?當函數模板和普通函數同名時,默認優先選擇普通函數:
template<typename T>
void SwapAll(T &a,T &b)
{
? ? T temp;
? ? temp = a;
? ? a = b;
? ? b = temp;
? ? cout << "模板函數" << endl;
? ? return;
}
void SwapAll(int & a, int & b)
{
? ? int temp;
? ? temp = a;
? ? a = b;
? ? b = temp;
? ? cout << "普通函數" << endl;
? ? return;
}
int main()
{ ??
? ? int a, b;
? ? a = 10;
? ? b = 20;
? ? SwapAll(a,b);
? ? cout << a << " " << b << endl;
}
?? ?強制調用模板函數:
int main()
{ ??
? ? int a, b;
? ? a = 10;
? ? b = 20;
? ? SwapAll<>(a,b);//強制使用模板函數
? ? SwapAll<int>(a, b);//強制使用模板函數,且提前告知類型,則不需要編譯器推導類型
? ? cout << a << " " << b << endl;
}
在編譯器進行函數模板的類型推導時,必須保持傳入的實參類型一直,若不一致則編譯器不會采用模板函數
當然非你強制使用模板函數
void SwapAll(T a,T b)
{
? ? cout << "模板函數" << endl;
? ? return;
}
void SwapAll(int ?a, int ?b)
{
? ? cout << "普通函數" << endl;
? ? return;
}
int main()
{ ??
? ? SwapAll(10,20);//普通函數
? ? SwapAll(10, 'a');//普通函數
? ? SwapAll('a', 'b');//模板函數
? ? SwapAll<int>(10, 'a');//模板函數
}
函數模板可以重載

函數模板的局限性:
?? ?當函數模板推導出T為數組或其他自定義類型數據 可能導致運算符不識別
第一種方法:重載運算符(推薦)
class Data1
{
? ? friend ostream& operator<<(ostream& out, Data1 ob);
private:
? ? int data;
public:
? ? Data1() {};
? ? Data1(int data)
? ? {
? ? ? ? this->data = data;
? ? }
};
ostream& operator<<(ostream& out, Data1 ob)
{
? ? out << ob.data << endl;
? ? return out;
}
template<typename T>
void SwapAll(T a)
{
? ? cout << a << endl;
? ? cout << "模板函數" << endl;
? ? return;
}

int main()
{ ??
? ? SwapAll('a');
? ? Data1 data(10);
? ? SwapAll(data);
? ? return 0;
}
該處,當模板函數識別到是Data1數據類型的時候,無法單純的輸出。必須重載運算符才能完成自定義類型的數據的
輸出

第二種:具體化函數模板
template<typename T>
void SwapAll(T a)
{
? ? cout << a << endl;
? ? cout << "模板函數" << endl;
? ? return;
}
class Data1
{
? ? friend void SwapAll<Data1>(Data1 data);
private:
? ? int data;
public:
? ? Data1() {};
? ? Data1(int data)
? ? {
? ? ? ? this->data = data;
? ? }
};
//函數模板具體化
template<> void SwapAll<Data1>(Data1 data)
{
? ? cout << data.data << endl;
? ? cout << "函數模板具體化" << endl;

}
int main()
{ ??
? ? SwapAll('a');
? ? Data1 data(10);
? ? SwapAll(data);
? ? return 0;
}
編譯器會先識別使用模板函數,但是發現自定義類型無法執行直接輸出,就去找有沒有具體化的函數模板

從上面的例子我們可以看出,無論是運算符的重載,還是函數模板的具體化。都是需要在類內處理的。

OK,了解完了函數模板后我們來看看類模板

---------------------------------------------------------------------------------------------------------------------------------

類模板:
?? ?當多個類的功能相同,僅僅是數據類型不同時,使用類模板。類模板用于實現類所需要數據類型參數化
template<class T1,class T2>
class Date
{
private:
? ? T1 a;
? ? T2 b;
public:
? ? Date() {};
? ? Date(T1 a, T2 b)
? ? {
? ? ? ? this->a = a;
? ? ? ? this->b = b;
? ? }
? ? void showdata()
? ? {
? ? ? ? cout << a << "-----" << b<<endl;
? ? }
};
int main()
{ ??
? ? Date<int, int> ob1(10, 20);
? ? Date<int, char> ob2(10,'a');
? ? ob1.showdata();
? ? ob2.showdata();
? ? return 0;
}
這個地方要強點一點的就是,類模板需要手動指定轉換類型。因為類的構造函數可以是無參構造,當我無參構造的時候是
無法判定類型的。這是一點于函數模板不同的地方

類模板的成員函數類外實現:
template<class T1,class T2>
class Date
{
private:
? ? T1 a;
? ? T2 b;
public:
? ? Date() {};
? ? Date(T1 a, T2 b);
? ? void showdata();
};
template<class T1,class T2>
Date<T1, T2>::Date(T1 a, T2 b)
{
? ? this->a = a;
? ? this->b = b;
}
template<class T1,class T2>
void Date<T1, T2>::showdata()
{
? ? cout << a << "----" << b << endl;
}
友元是一種定義在類外部的普通函數或類,但它需要在類體內進行說明,
為了與該類的成員函數加以區別,在說明時前面加以關鍵字friend。
友元不是成員函數,但是它可以訪問類中的私有成員
函數模板作為類模板的友元:
?? ?template<class T1,class T2>
class Date
{
? ? template<typename T3,typename T4>
? ? friend void showdata(Date<T3, T4>& ob);
private:
? ? T1 a;
? ? T2 b;
public:
? ? Date() {};
? ? Date(T1 a, T2 b);
};
template<class T1,class T2>
Date<T1, T2>::Date(T1 a, T2 b)
{
? ? this->a = a;
? ? this->b = b;
}
template<typename T3,typename T4>
void showdata(Date<T3,T4> &ob)
{
? ? cout << ob.a << "----" << ob.b << endl;
}
int main()
{ ??
? ? Date<int, int> ob1(10, 20);
? ? Date<int, char> ob2(10,'a');
? ? showdata(ob1);
? ? showdata(ob2);
? ? return 0;
}

普通函數作為類模板的友元
?? ?相比于函數模板,普通函數就只需要將模板相關的關鍵字刪除,并且指定模板的類型即可。如下:
template<class T1,class T2>
class Date
{
? ? friend void showdata(Date<int,int>& ob);
private:
? ? T1 a;
? ? T2 b;
public:
? ? Date() {};
? ? Date(T1 a, T2 b);
};
template<class T1,class T2>
Date<T1, T2>::Date(T1 a, T2 b)
{
? ? this->a = a;
? ? this->b = b;
}
void showdata(Date<int, int>&ob)
{
? ? cout << ob.a << "----" << ob.b << endl;
}
int main()
{ ??
? ? Date<int, int> ob1(10, 20);
? ? Date<int, char> ob2(10,'a');
? ? showdata(ob1);
? ? return 0;
}

總結

以上是生活随笔為你收集整理的函数模板与类模板的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。