C Template 基礎篇(二) 類模板

2021-07-27 12:19:06 字數 4181 閱讀 1204

template所代表的泛型程式設計是c++語言中的重要的組成部分,我將通過幾篇blog對這半年以來的學習做乙個系統的總結,本文是基礎篇的第二部分。

類模板tips

特化與偏特化

類模板也是公共邏輯的抽象,通常用來作為容器(例如:vector)或者行為(例如:clonable)的封裝。

下面定義了乙個printer類模板,負責列印以及轉化為string。

template

class

printer

string&&

to_string()

;//定義在內部

void

print()

private

: t t;};

//定義在外部

template

string&& printer::

to_string()

printer p(1

);//error

printer<

int> p(

1);//ok

與函式模板不同,類模板不能推斷例項化。所以你只能顯示指定型別引數使用printerp(1),而不能讓編譯器自行推斷printer p(1)

類模板的成員函式既可以定義在內部,也可以定義在外部。定義在內部的被隱式宣告為inline,定義在外部的類名之前必須加上template的相關宣告。

我們還可以把類模板和函式模板結合起來,定義乙個含有成員函式模板的類模板。

template

class

printer

//成員函式模板

template

void

add_and_print

(const u& u)

;private

: t t;};

//注意這裡要有兩層template的說明

template

template

void printer::

add_and_print

(const u& u)

printer<

int> p(

42);p.

add_and_print

(1.1);

//自動推斷u為double,列印出43.1

template

class

printer

static

int s_value;

private

: t t;};

template

//注意這裡的定義方式

int printer

::s_value =1;

printer<

int>

pi(1)

;printer<

int>

pi2(1

);printer<

double

>

pd(1.0)

;pi.s_value +=1;

//pi和pi2中的改變了,pd的沒改變

其實這個結論是顯然的,static成員屬於例項化後的類,不同的例項化當然有不同static成員。就像上面的例子一樣,pi.s_value += 1只影響到了printer,而不會影響到printer

函式模板中的static區域性變數也有類似的工作方式。

為了節省資源,類模板例項化時並不是每個成員函式都例項化了,而是使用到了哪個成員函式,那個成員函式才例項化。

template

class

printer

void

print()

private

: t t;};

class

empty

;empty e;

printer

p(e)

;//ok

雖然成員函式print無法通過編譯,但是因為沒有使用到,也就沒有例項化print,所以沒有觸發編譯錯誤。

為了簡化**,我們可以使用typedef為類模板的某個例項定義乙個別名,也可以使用using語句固定乙個或多個型別引數(這有點偏特化的意思了)。

typedef std:

:pair<

int,

int>

pairofint;

//ok,為std::pair定義了乙個別名

template using withnum = std:

:pairint>

;//ok,相當於定義了乙個std::pair的偏特化

pairofint poi;

//實際型別,std::pair

withnum:string> strs;

//實際型別,std::pair

withnum<

int>

ints;

//實際型別,std::pair

就像函式模板過載那樣,你可以通過特化(偏特化)類模板來為特定的型別指定你想要的行為。類模板的特化(偏特化)只需要模板名稱相同並且特化列表<>中的引數個數與原始模板對應上即可,模板引數列表不必與原始模板相同模板名稱相同。乙個類模板可以有多個特化,與函式模板相同,編譯器會自動例項化那個最特殊的版本。

template

//基本模板

classs}

;template<

>

//特化

class

s<

int> }

;template

//偏特化

class

s>};

template

//另外乙個偏特化

class

s<

t(u)

>};

intfunc

(int i)

s<

float

>

s1;s1.info()

;//呼叫base模板

s<

int>

s2;s2.info()

;//呼叫int特化版本

s<

float

*> s3;

s3.info()

;//呼叫t*特化版本

s<

decltype

(func)

> s4;

s4.info()

;//呼叫函式特化版本

提供了所有型別實參的特化是完全特化,只提供了部分型別實參或者t的型別受限(例如:t*)的特化被認為是不完整的,所以也被稱為偏特化完全特化的結果是乙個實際的class,而偏特化的結果是另外乙個同名的模板。

除了可以特化類模板之外,還可以對類模板中的成員函式和普通靜態成員變數進行特化。

template

class

sstatic

int code;};

template

int s

::code =10;

template<

>

int s<

int>

::code =

100;

//普通靜態成員變數的int特化

template<

>

void s<

int>::

info()

s<

float

>

s1;s1.info()

;//普通版本

printf

("code is: %d\n"

, s1.code)

;//code = 10

s<

int>

s2;

s2.info()

;//int特化版本

printf

("code is: %d\n"

, s2.code)

;//code = 100

C Template 基礎篇(三) 引數魔法

template所代表的泛型程式設計是c 語言中的重要的組成部分,我將通過幾篇blog對這半年以來的學習做乙個系統的總結,本文是基礎篇的第三部分。除了使用型別作為模板的引數之外,模板引數有更多的用法,以下做個詳細介紹。我們可以通過給模板指定預設實參,為使用者推薦合適的預設設定,讓使用者在只指定部分 ...

python基礎學習筆記(二)類和物件

class bird object def init self,sound magic mehod 前後兩個下劃線 如 add self.sound sound dict print init sound sound def chirp self self 該函式可在同一類中被呼叫 print bi...

C 學習筆記(二)類和物件基礎

成員函式 注意 兩個冒號 int car size 函式size是car類的成員函式,只能通過物件 物件指標 物件引用才能呼叫。private 私有成員 public 公有成員 protected 保護成員 1 類成員函式的內部可訪問 當前物件和同類其他物件的全部屬性,函式。2 類的成員函式以外可訪...