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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

从零开始学C++之模板(三):缺省模板参数(借助标准模板容器实现Stack模板)、成员模板、关键字typename...

發布時間:2023/11/29 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从零开始学C++之模板(三):缺省模板参数(借助标准模板容器实现Stack模板)、成员模板、关键字typename... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、缺省模板參數

回顧前面的文章,都是自己管理stack的內存,無論是鏈棧還是數組棧,能否借助標準模板容器管理呢?答案是肯定的,只需要多傳一個模板參數即可,而且模板參數還可以是缺省的,如下:


template <typename T, typename CONT = std::deque<T> >
class Stack
{


private:

????CONT?c_;
};


如果沒有傳第二個參數,默認為deque 雙端隊列,當然我們也可以傳遞std::vector<T>

?

下面程序借助標準模板容器管理內存來實現stack模板類:


Stack.h:

?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
? #ifndef?_STACK_H_
#define?_STACK_H_

#include?<exception>
#include?<deque>
using? namespace?std;

template?< typename?T,? typename?CONT?=?deque<T>?>
class?Stack
{
public:
????Stack()?:?c_()
????{
????}
????~Stack()
????{
????}

???? void?Push( const?T?&elem)
????{
????????c_.push_back(elem);
????}
???? void?Pop()
????{
????????c_.pop_back();
????}
????T?&Top()
????{
???????? return?c_.back();
????}
???? const?T?&Top()? const
????{
???????? return?c_.back();
????}
???? bool?Empty()? const
????{
???????? return?c_.empty();
????}
private:
????CONT?c_;
};

#endif? //?_STACK_H_

?


main.cpp:

?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
? #include? "Stack.h"
#include?<iostream>
#include?<vector>
using? namespace?std;


int?main( void)
{
???? /*Stack<int>?s;*/
????Stack< int,?vector< int>?>?s;
????s.Push( 1);
????s.Push( 2);
????s.Push( 3);

???? while?(!s.Empty())
????{
????????cout?<<?s.Top()?<<?endl;
????????s.Pop();
????}
???? return? 0;
}

?

?

輸出為 3 2 1


即如果沒有傳遞第二個參數,堆棧和壓棧等操作直接調用deque<int> 的成員函數,也由deque<int> 管理內存。

如程序中傳遞vector<int> ,則由vector<int> 成員函數處理。


二、成員模板

來看下面的例子:


?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
? #include?<iostream>
using? namespace?std;


template?< typename?T>
class?MyClass
{
private:
????T?value;
public:
???? void?Assign( const?MyClass<T>?&x)
????{
????????value?=?x.value;
????}
};

int?main( void)
{
????MyClass< double>?d;
????MyClass< int>?i;

????d.Assign(d);???????? //?OK
????d.Assign(i);???????? //?Error
???? return? 0;
}

?

?

因為i 和 d 的類型不同,故會編譯出錯。可以用成員模板的方法解決:
C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
? #include?<iostream>
using? namespace?std;

template?< typename?T>
class?MyClass
{
private:
????T?value;
public:
????MyClass()?{}
???? template?< class?X>
????MyClass( const?MyClass<X>?&x)?:?value(x.GetValue())
????{

????}
???? template?< class?X>
???? void?Assign( const?MyClass<X>?&x)
????{
????????value?=?x.GetValue();
????}
????T?GetValue()? const
????{
???????? return?value;
????}
};

int?main( void)
{
????MyClass< double>?d;
????MyClass< int>?i;
????d.Assign(d);???????? //?OK
????d.Assign(i);???????? //?OK

????MyClass< double>?d2(i);

???? return? 0;
}





為了支持 ?MyClass<double>?d2(i); 故也要將拷貝構造函數實現為成員模板,同理,如果想支持 d = i ; 也要講賦值運算符實現為成員
模板。 實際上auto_ptr<class> 中的實現就使用了成員模板,因為要支持類似下面的運算:
auto_ptr<X> x;
auto_ptr<Y> y;
x = y;

三、typename 關鍵字
看下面的例子:
C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
? #include?<iostream>
using? namespace?std;

template?< typename?T>
class?MyClass
{
private:
???? typename?T::SubType?*ptr_;
};

class?Test
{
public:
???? typedef? int?SubType;
};
int?main( void)
{
????MyClass<Test>?mc;
???? return? 0;
}



typename?T::SubType?*ptr_; 如果前面沒有typename 修飾,則SubType會被認為是T類型內部的靜態數據成員,推導下去,* 就不再認
為是指針,而被認為是乘號,編譯的時候就出錯了。加上修飾,就知道SubType 是T 內部的自定義類型,ptr是指向這種類型的指
針,編譯通過。


?


四、派生類與模板、面向對象與泛型編程

(一)、派生類與模板


1、為了運行的效率,類模板是相互獨立的,即獨立設計,沒有使用繼承的思想。對類模板的擴展是采用適配器(adapter)來完成的。通用性是模板庫的設計出發點之一,這是由泛型算法(algorithm)和函數對象(functor)等手段達到的。


2、派生的目標之一也是代碼的復用和程序的通用性,最典型的就是MFC,派生類的優點是可以由簡到繁,逐步深入,程序編制過程中可以充分利用前面的工作,一步步完成一個復雜的任務。


3、模板追求的是運行效率,而派生追求的是編程的效率。


(二)、面向對象與泛型編程

1、面向對象與泛型都依賴于某個形式的多態


面向對象

動態多態(虛函數)

泛型

靜態多態(模板類,模板函數)


2、面向對象中的多態在運行時應用存在繼承關系。我們編寫使用這些類的代碼,忽略基類與派生類之間的類型差異。只要使用基類指針或者引用,基類類型對象、派生類類型對象就可以共享相同的代碼。


3、在泛型編程中,我們所編寫的類和函數能夠多態地用于編譯時不相關的類型。一個類或一個函數可以用來操縱多種類型的對象。


?

參考:

C++ primer 第四版
Effective C++ 3rd
C++編程規范

?


?

總結

以上是生活随笔為你收集整理的从零开始学C++之模板(三):缺省模板参数(借助标准模板容器实现Stack模板)、成员模板、关键字typename...的全部內容,希望文章能夠幫你解決所遇到的問題。

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