C 模板總結

2021-09-02 08:09:42 字數 4095 閱讀 6051

前提:我們要實現乙個通用的交換函式swap,就是讓它適用於任何乙個型別。比如:int,char,double......,但是我們要寫很多交換的函式,對swap函式進行過載。那我們如何解決這個問題?可不可以給編譯器乙個模子,讓編譯器來給我們實現不同型別的轉化?

1.概念:函式模板代表了乙個函式家族,在使用時被引數化,根據實參型別產生特定的函式。

2.函式模板格式

template//不能用struct代替class

t add(const t& a,const t&b)

int main()

int main()

上述**為何會出錯?

因為在編譯階段,看到實參a時打算將t推演成int型別,然後又遇到實參d,是double型別,所以編譯器就不知道是將t推演成哪乙個引數,就會很直接的報錯。

所以,這裡的錯誤處理方式有兩種:1.自己強轉;2.使用顯示例項化

(2)顯示例項化:在函式名字後的<>中指定模板引數的實際型別

templatet add(const t& a,const t&b)

int main()

5.模板函式的匹配原則

(1)乙個非模板函式可以和乙個同名的函式模板同時存在,而且該函式模板任然可以被例項化。

(2)如果乙個非模板函式和同名的函式模板同時存在,那麼編譯器會優先呼叫非模板引數。

template//函式模板

t2 add(const t1& a,const t2&b)

int add(const int a, const int b)//非模板函式

int main()

void pushback(const t& mydata)

void popback()

int size()

t& operator(int pos)

~myvector() }

private:

t*data;

int size;

int capacity;

};int main()

類模板的例項化和函式模板的例項化不同,類模板例項化需要在類模板名字後加<>,然後將型別放在<>即可。

模板引數有兩種,一種是型別引數,另一種是非型別引數。

型別引數就是在模板引數列表中,跟class或者typename之類的引數型別名稱

非型別形參就是用乙個常量作為類模板的乙個引數,在類模板中可以將這個引數當成常量來使用。

//定義乙個靜態的陣列

templateclass array

const t& operator(int index)const

int size()const

bool empty()const

private:

t _array[n];//n在類中是個常量,可以直接使用

int _size;

};

需要注意的是:浮點型(float)、類物件和字串是不允許作為非型別模板引數的,非型別的模板引數必須在編譯器就能確認結果,可以將它定義成乙個巨集的常量。

通常情況下,模板可以實現一些與型別無關的**,但是對於一些特殊型別的可能會得到一些錯誤的結果。所以我們就需要對模板進行特化,就是在原模版的基礎上,針對特殊型別所進行的特殊的實現方式。模板的特化分成:函式模板特化和類模板特化。

1.函式模板的特化

步驟:(1)必須有乙個基礎的函式模板

(2)在關鍵字templaste後邊加<>

(3)<>中需要加指定的型別

(4)引數列表必須和基礎函式模板引數型別完全相同

template<> bool isequal(char*& left, char*& right) 

其實這麼實現沒有必要,我們可以採用更加簡單的直接寫出函式就可以。

2.類模板的特化

類模板的特化分成兩種,一種全特化,另一種是偏特化。

(1)全特化就是模板引數列表中所有的引數都被確化

templateclass data

private:

t1 _d1;

t2 _d2;

};template<>

class data//全特化

private:

int _d1;

char _d2;

};

(2)偏特化是對模板引數進行進一步的條件限制的特化版本

第一種:部分特化

templateclass data//對第二個引數型別特化成char

private:

t _d1;

char _d2;

};

第二種:對引數更進一步的條件限制

template //兩個引數特化成指標型別

class data

private:

t1 _d1;

t2 _d2;

};

1.實現乙個通用的拷貝函式

拷貝我們可以使用memcpy函式,也可以用for迴圈乙個乙個的賦值,但是我們需要了解到這兩種拷貝的優缺點。

memcpy函式可以對任意的內建型別進行拷貝,但是拷貝自定義型別的時候就會出錯,而且它是淺拷貝的方式。

迴圈賦值的方式雖然可以對自定義型別進行拷貝,但是**的效率比較差。

所以我們在實現通用的拷貝函式的時候,可以將這兩種拷貝方式結合在一起。

bool ispod(const char *name)

; for (size_t i = 0; i < sizeof(t) / sizeof(t[0]); i++)

return false;

}templatevoid copy( t* dst,t* src,size_t size)

}int main()

; string strarr2[3];

copy(strarr2, strarr1, 3);//用迴圈賦值

int a = 100;

int b = 0;

copy(&b, &a, 4);//用memcpy

system("pause");

return 0;

}

2.型別萃取

struct truetype//內建型別

};struct falsetype//自定義型別

};templatestruct typetraits

;template<> struct typetraits;

template<> struct typetraits;

template<> struct typetraits;

template<> struct typetraits;

template<> struct typetraits;

//......

templatevoid copy(t* dst, t* src, size_t size)

}int main()

; string strarr2[3];

copy(strarr2, strarr1, 3);

int a = 100;

int b = 0;

copy(&b, &a, 4);

system("pause");

return 0;

}

我們使用兩個結構體區分開了是自定義型別還是內建型別?

當我們拷貝strarr1和strarr2的時候,由於typetraits沒有被特化,所以該類模板中的ispodtype剛好為類falsetype,而falsetype中get函式返回true,自定義型別使用賦值方式拷貝

當我們拷貝a和b的時候,由於typetraits被特化,所以該類模板中的ispodtype剛好為類truetype,而truetype中get函式反悔true,證明是內建型別,內建型別需要用memcpy

C 模板總結

1 模板概念 模板是泛型程式設計的基礎。所謂泛型程式設計就是編寫與型別無關的邏輯 是一種復用的方式。模板分為模板函式和模板類。2 typename 與 class template 採用 class 來宣告模板 class template 採用 typename 來宣告模板 class 這兩種一般...

C 基礎 C 模板總結

模板是泛型程式設計的基礎,分為模板函式和模板類 泛型程式設計就是與型別無關的邏輯 是一種復用的方式。那麼為什麼要有泛型程式設計呢?c 是一門強型別的語言,無法像動態語言那樣,可以寫一段邏輯 把任意型別傳進去。為了解決這個問題所以有了泛型程式設計,通過把通用的邏輯設計為模板,可以擺脫型別的限制,提供了...

C 模板類總結

一 模板簡介 在c 中,模板讓程式設計師能夠定義一種適用於不同型別的物件行為。這聽起來有點像巨集,但巨集不是型別安全的,而模板是型別安全的。二 模板宣告語法 關鍵字template標誌著模板類宣告的開始,接下來是模板引數列表。該引數列表包含關鍵字typename,它定義了模板引數objecttype...