欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++ 泛型編程詳解

 更新時間:2020年02月06日 16:00:07   作者:LWL20201104  
這一篇介紹一下 C++ 編程中與面向對象并列的另一大分支——泛型編程,這一篇主要介紹函數模板、類模板和成員模板三大部分,需要的朋友可以參考下

泛型編程與面向對象編程的目標相同,即使重用代碼和抽象通用概念的技術更加簡單。但是面向對象編程強調編程的數據方面,泛型編程強調的是獨立于特定數據類型。

這一篇介紹一下 C++ 編程中與面向對象并列的另一大分支——泛型編程,這一篇主要介紹函數模板、類模板和成員模板三大部分

如有侵權,請聯系刪除,如有錯誤,歡迎大家指正,謝謝

泛型編程

模板是泛型編程的一種重要思想,STL(Standard Template Library,標準模板庫)是采用模板實現的一個實例
函數模板

對比函數重載(同一作用域內函數名相同,參數列表不同的函數),函數模板只需要一個函數就實現了函數重載的部分功能(參數個數相同類型不同,函數重載需要定義多個同名參數列表不同的函數)

template<typename T, typename Y> // 這也可以寫 template<class T, class Y> 此處的 class 和 typename 作用相同
void tfunc(T& t, Y& y) {
 cout << t << " " << y << endl;
}
int n = 2;
double d = 2.1;
tfunc(n, d);

// 運行結果:2 2.1

函數模板具體化,函數模板具體化就是將某一(某幾)個要處理的類型單獨處理,需要單獨寫一個實現,形式是 template<> void fun(type& t);,函數模板的具體化和普通函數可以同時存在,調用順序是 普通函數 > 函數模板具體化 > 模板函數

// ====== 測試一:函數模板針對特殊數據類型具體化 ======
struct Node {
 int val;
 Node* next;
};
// 函數模板
template<typename T> 
void tfunc(const T& t) {
 cout << "template: " << t << endl;
}
// 函數模板具體化(用于處理Node類型數據)
template<> 
void tfunc<Node>(const Node& node) {
 cout << "template<Node>: " << node.val << endl;
}
// 函數模板具體化(用于處理int類型數據)
template<> 
void tfunc<int>(const int& n) {
 cout << "template<int>: " << n << endl;
}
// 普通函數
void tfunc(const int& n) {
 cout << "tfunc(): " << n << endl;
}
double d = 2.1;
tfunc(d); // 函數模板未具體化double類型函數,調用模板
Node node{ 2, nullptr };
tfunc(node); // 函數模板具體化Node類型函數,調用函數模板的具體化
int n = 2;
tfunc(n); // 函數模板具體化int類型函數,也存在普通函數,調用普通函數
// ====== 測試二:函數模板部分具體化 ======
template<typename T1, typename T2>
void tfunc(T1 t1, T2 t2) {
 cout << typeid(T1).name() << " and " << typeid(T2).name() <<": " << t1 << " " << t2 << endl;
}
template<typename T1>
void tfunc(T1 t1, int i) {
 cout << typeid(T1).name() << " and " << "int: " << t1 << " " << i << endl;
}
template<typename T2>
void tfunc(long l, T2 t2) {
 cout << "long and " << typeid(T2).name() << ": " << l << " " << t2 << endl;
}
template<>
void tfunc(short l, int i) {
 cout << "long and int: " << l << " " << i << endl;
}
// 分別調用以上四個模板函數
tfunc(char('c'), char('c'));
tfunc(char('c'), int(10));
tfunc(long(10), char('c'));
tfunc(short(10), int(10));

函數模板實例化,讓編譯器生成指定類型的函數定義,不用寫函數的實現,形式是 template void fun(type& t);

// 函數模板
template<typename T> 
void tfunc(const T& t) {
 cout << "template: " << t << endl;
}

// 函數模板實例化,不用寫函數的實現,編譯器會生成該類型的模板具體化函數
template void tfunc<char>(const char& c);

類模板

類模板可以指定默認模板參數(函數模板不可以),跟函數參數的默認值一樣,必須從右向左連續(xù)賦值默認類型,如果實例化對象時又傳遞了類型,默認類型會被覆蓋掉,跟函數參數是一樣的
創(chuàng)建對象時需要傳遞模板參數列表,模板參數列表加在類名后面 ClassName< typename T > classN; 如果類的模板參數列

表有默認值,可以不傳模板參數,但一定要加 <> 如 ClassName< > classN; 創(chuàng)建堆區(qū)對象的時候,所有的類名稱后面都要加模板參數列表,如 ClassName< typename T >* classN = new ClassName< typename T>; 除了類內,其他地方出現 ClassName 的地方一般都要加模板參數列表

template<typename T = int, typename Y = char> // 此處指定了模板默認參數,部分指定必須從右到左指定
class Test {
public:
 Test(T t, Y y) : t(t), y(y) {
 }
 void tfunc();
private:
 T t;
 Y y;
};
template<typename T, typename Y> // 類模板的函數在類外實現,需要加上模板參數列表,但不需要加指定的默認模板參數
void Test<T, Y>::tfunc() { // 類外使用Test需要加模板參數
 cout << t << " " << y << endl;
}
int n = 2;
double d = 2.1;
Test<int, double> test(n, d); // 此處如果使用默認模板參數可定義為 Test<> test(int(2), char('a'));
test.tfunc();
// 運行結果:2 2.1

類模板的繼承,類模板被繼承后參數的傳遞方式主要有兩種,一種是直接在子類繼承父類的時候,為父類指定固定的類型,二是通過子類模板參數列表傳遞

// ====== 測試一 ======
template<typename T, typename Y>
class A {
public:
 A(T t, Y y) {
 }
};
class Test : public A<int, double> { // 父類是類模板,子類是普通類
public:
 Test() : A<int, double>(2, 2.1) {
 }
};
Test();
// ====== 測試二 ======
template<typename T, typename Y>
class A {
public:
 A(T t) {
 }
};
template<typename X, typename Z, typename P>
class Test : public A<X, P> {
public:
 Test(X x, Z z, P p) : A<X, P>(x) {
 }
};
Test<int, double, char>(int(2), double(2.1), char('a'));

類模板的多態(tài),在創(chuàng)建對象時,分為子類沒有模板(CFather<short, char>*cf = new CSon;)和子類有模板(CFather<short, char> *cf = new CSon<short, int, char>)兩種,子類和父類的模板參數列表可以不一樣,但一定要對應好

// ====== 測試一 ======
template<typename T, typename Y> 
class A {
public:
 virtual void tfunc(T t, Y y) = 0;
};
class Test : public A<int, double> { 
public:
 virtual void tfunc(int n, double d) {
 cout << n << " " << d << endl;
 }
};
// 父類是類模板,子類是普通類,在多態(tài)情況下父類需要指定模板參數,子類就不用了
A<int, double>* a = new Test;
a->tfunc(2, 2.1);
// 運行結果:2 2.1
// ====== 測試二 ======
template<typename T, typename Y> 
class A {
public:
 virtual void tfunc(T t, Y y) = 0;
};
template<typename X, typename Z, typename P>
class Test : public A<X, P> {
public:
 virtual void tfunc(X x, P p) {
 cout << x << " " << p << endl;
 }
};

// 父類是類模板,子類是類模板,在多態(tài)情況下父類和子類都需要指定模板參數
A<int, double>* a = new Test<int, char, double>;
a->tfunc(2, 2.1);
// 運行結果:2 2.1

類模板具體化,類模板的具體化分為部分具體化和全部具體化兩種

template<typename T1, typename T2>
class Test {
public:
 Test() {
 cout << "T1 and T2" << endl;
 }
};
// 部分具體化
template<typename T1>
class Test<T1, int> {
public:
 Test() {
 cout << "T1 and int" << endl;
 }
};
// 部分具體化
template<typename T2>
class Test<long, T2> {
public:
 Test() {
 cout << "long and T2" << endl;
 }
};
// 全部具體化
template<>
class Test<long, int> {
public:
 Test() {
 cout << "long and int" << endl;
 }
};
// 分別創(chuàng)建上面四個類
Test<char, char>();
Test<char, int>();
Test<long, char>();
Test<long, int>();

成員模板

成員模板簡單說就是模板中的模板

class Base1 { };
class Base2 { };
class Test1 : public Base1 { };
class Test2 : public Base2 { };
template<typename T1, typename T2> 
class Pair {
public:
 T1 t1;
 T2 t2;
 Pair(T1 t1, T2 t2) : t1(t1), t2(t2) {
 }
 // 類模板中的成員模板
 template<typename U1, typename U2>
 Pair(const Pair<U1, U2>& pair) : t1(pair.t1), t2(pair.t2){
 }
};
Pair<Base1*, Base2*>(Pair<Test1*, Test2*>(new Test1, new Test2));

如果未特殊說明,以上測試均是在win10 vs2017 64bit編譯器下進行的

總結

以上所述是小編給大家介紹的C++ 泛型編程,希望對大家有所幫助!

相關文章

  • C++中的六個函數

    C++中的六個函數

    本文給大家介紹了C++中的六個函數,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2018-05-05
  • windows?使用ffmpeg?.a靜態(tài)庫讀取Wav音頻并保存PCM的方法

    windows?使用ffmpeg?.a靜態(tài)庫讀取Wav音頻并保存PCM的方法

    這篇文章主要介紹了windows?使用ffmpeg?.a靜態(tài)庫讀取Wav音頻并保存PCM,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-02-02
  • 實例詳解C++中指針與引用的區(qū)別

    實例詳解C++中指針與引用的區(qū)別

    引用是C++引入的重要機制(C語言沒有引用),它使原來在C中必須用指針來實現的功能有了另一種實現的選擇,在書寫形式上更為簡潔,那么引用的本質是什么,它與指針又有什么關系呢?這篇文章主要給大家介紹了關于C++中指針與引用的區(qū)別,需要的朋友可以參考下
    2021-07-07
  • 將CString字符串輸入轉化成整數的實現方法

    將CString字符串輸入轉化成整數的實現方法

    下面小編就為大家?guī)硪黄獙String字符串輸入轉化成整數的實現方法。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • Linux?C/C++?timeout命令實現運行具有時間限制功能

    Linux?C/C++?timeout命令實現運行具有時間限制功能

    inux?timeout命令的一個屬性是時間限制??梢詾槿魏蚊钤O置時間限制。如果時間到期,命令將停止執(zhí)行,這篇文章主要介紹了Linux?C/C++?timeout命令實現(運行具有時間限制),需要的朋友可以參考下
    2023-02-02
  • 數據結構之鏈式二叉樹詳解

    數據結構之鏈式二叉樹詳解

    所謂二叉樹遍歷 (Traversal) 是按照某種特定的規(guī)則,依次對二叉樹中的節(jié)點進行相應的操作,并且每個節(jié)點只操作一次。本文通過代碼示例詳細介紹了C語言中的鏈式二叉樹,需要的朋友可以參考一下
    2023-04-04
  • C語言詳細分析講解struct與union使用方法

    C語言詳細分析講解struct與union使用方法

    最近開始自學C語言,從最基礎部分的開始學起。今天看書的時候注意到了struct和union似乎很像,除了名字不同,看起來幾乎沒有區(qū)別。<BR>既然C中定義了struct和union兩個關鍵字,那么它們肯定是有區(qū)別的,在查了一些資料之后我來總結一下他們的使用
    2022-04-04
  • 深入理解c++實現Qt信號和槽機制

    深入理解c++實現Qt信號和槽機制

    信號和槽機制是 Qt 的核心機制,可以讓編程人員將互不相關的對象綁定在一起,實現對象之間的通信,本文就來深入理解c++實現Qt信號和槽機制,感興趣的可以了解一下
    2023-08-08
  • C++抽象基類講解

    C++抽象基類講解

    這篇文章主要介紹了C++抽象基類講解,象基類abstract base class簡稱ABC,C++實現繼承的時候,需要保證派生類和基類之間是一種is-a的關系。在大多數時刻,這樣的關系是沒有問題的,然而在一些特殊的情況可能會遇到問題,下面來看看文章的具體介紹吧
    2022-01-01
  • C++實現十進制數轉換為二進制數的數學算法

    C++實現十進制數轉換為二進制數的數學算法

    這篇文章和大家分享一下我個人對十進制數轉換為二進制數的想法,目前暫時更新只整數十進制的轉換,后續(xù)會更新帶有小數的進制轉換,代碼使用c++實現
    2021-09-09

最新評論