1.定義模板
16.1.1 函數模板
我們可以定義一個通用的函數模板,而不是爲每個類型都定義一個新函數
我們可以這麼做:
#include <memory>
#include <cstring>
template <typename T>
int compire(const T &v1,const T &v2)
{
if(v1<v2)
{
return -1;
}
if(v1>v2)
{
return 1;
}
return 0;
}
int main()
{
printf("%d\n",compire(1,2));
return 0;
}
類模板
我們發現我們的模板有一個叫T的參數
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
int add(T a,T b)
{
return a+b;
}
};
#endif //TEST_TEMPLATE_H
調用處
#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
BlobA<int> a;
std::cout<<a.add(1,2)<<std::endl;
return 0;
}
實例化類模板:
我們已經多次見到,當使用一個類模板的時候,我們必須要提供額外的信息是顯示模板實參列表,它們被綁定到模板參數。編譯器使用這些模板實參來實例話這些特定的類。
看到書這裏是這麼寫了一個demo勾起了我的疑問
#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
BlobA<int> a = {0,1,2};
std::cout<<a.add(1,2)<<std::endl;
return 0;
}
爲什麼類可以被初始化爲{0,1,2}
原來構造函數裏重載在這裏
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
BlobA(std::initializer_list<T> il)
{
}
int add(T a,T b)
{
return a+b;
}
};
#endif //TEST_TEMPLATE_H
這裏簡單說一下自定義類型使用initializer_list
c++11也提供了方法,讓用戶可以在自定義類型(一般指類)中使用初始化列表。
我們看一下實例化後的類
BlobA(std::initializer_list il)
{
for (auto a : il)
{
std::cout<<a<<std::endl;
}
}
結果是0,1,2,3
我們繼續看書後面的內容
智能指針使用模板
std::shared_ptr<BlobA<int>> data;
data是一個shared_ptr的實例,此shared_ptr保存了一個類型爲T的對象的vector實例
1.定義模板
16.1.1 函數模板
我們可以定義一個通用的函數模板,而不是爲每個類型都定義一個新函數
我們可以這麼做:
#include <memory>
#include <cstring>
template <typename T>
int compire(const T &v1,const T &v2)
{
if(v1<v2)
{
return -1;
}
if(v1>v2)
{
return 1;
}
return 0;
}
int main()
{
printf("%d\n",compire(1,2));
return 0;
}
類模板
我們發現我們的模板有一個叫T的參數
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
int add(T a,T b)
{
return a+b;
}
};
#endif //TEST_TEMPLATE_H
調用處
#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
BlobA<int> a;
std::cout<<a.add(1,2)<<std::endl;
return 0;
}
實例化類模板:
我們已經多次見到,當使用一個類模板的時候,我們必須要提供額外的信息是顯示模板實參列表,它們被綁定到模板參數。編譯器使用這些模板實參來實例話這些特定的類。
看到書這裏是這麼寫了一個demo勾起了我的疑問
#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
BlobA<int> a = {0,1,2};
std::cout<<a.add(1,2)<<std::endl;
return 0;
}
爲什麼類可以被初始化爲{0,1,2}
原來構造函數裏重載在這裏
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
BlobA(std::initializer_list<T> il)
{
}
int add(T a,T b)
{
return a+b;
}
};
#endif //TEST_TEMPLATE_H
這裏簡單說一下自定義類型使用initializer_list
c++11也提供了方法,讓用戶可以在自定義類型(一般指類)中使用初始化列表。
我們看一下實例化後的類
BlobA(std::initializer_list il)
{
for (auto a : il)
{
std::cout<<a<<std::endl;
}
}
結果是0,1,2,3
我們繼續看書後面的內容
智能指針使用模板
std::shared_ptr<BlobA<int>> data;
data是一個shared_ptr的實例,此shared_ptr保存了一個類型爲T的對象的vector實例
類模板的成員函數
我們既可以在類模板內部也可以在類模板外部爲其定義成員函數,且定義在模板內部的成員函數被隱式聲明爲內斂函數。
定義在模板外的類模板成員函數必須以template開始
與往常一樣當我們在類外定義一個成員函數的時候,必須說明成員屬於哪一個類。而且一個模板生成類的名字中必須包含其模板實參。當我們定義一個成員函數的時候,必須說明成員屬於哪個類。而且從一個模板生成類的名字中必須包含模板的實參。當我們定義一個成員函數的時候,模板實參與模板形參相同。對於一個成員函數,對應blob的成員應該是這個樣子的。
template <typename T>
ret-type Blob<T>::member-name(parm-list)
注意模板的定義和聲明不能分開爲兩個文件,因爲在編譯的時候並不會生成具體類,只有在調用的時候會,所以需要包含.cc,但是這並不是一個好方案,所以還是寫在一個.h文件中比較好
比如一個放在.h中 一個放在.cc中
類模板與另一個模板間的友好關係最常見的形式是建立實例以及友元間的友好關係
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
#include <vector>
#include <iostream>
// Created by root on 20-2-27.
//
template <typename >class BlobPtr;
template <typename >class Blob;
template <typename T>
bool operator == (const Blob<T>&,const Blob<T>&);
template <typename T>class BlobA{
public:
friend class BlobPtr<T>;
friend bool operator == <T>(const Blob<T>&,const Blob<T>&);
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
BlobA(std::initializer_list<T> il)
{
for (auto a : il)
{
std::cout<<a<<std::endl;
}
}
int add(T a,T b);
};
template <typename T>
int BlobA<T>::add(T a, T b) {
return a+b;
}
#endif //TEST_TEMPLATE_H
模板類型別名
模板類型的特性,typedef BlobA data2;
另一種方式
希望指定別名的不是一個實例化的模板類,而是一個模板
template <typename T>using partNo = BlobA<unsigned>;
類模板的static成員
與其他任何類都相同,類模板也可以聲明static成員。
template <typename T>class BlobA{
public:
static std::size_t count(){ return ctr;};
static std::size_t ctr;
private:
};
//初始化
template <typename T>size_t BlobA<T>::ctr = 0;
//使用
int main()
{
std::cout<<partNo<int>::count()<<std::endl;
return 0;
}
類模板的成員函數
我們既可以在類模板內部也可以在類模板外部爲其定義成員函數,且定義在模板內部的成員函數被隱式聲明爲內斂函數。
定義在模板外的類模板成員函數必須以template開始
與往常一樣當我們在類外定義一個成員函數的時候,必須說明成員屬於哪一個類。而且一個模板生成類的名字中必須包含其模板實參。當我們定義一個成員函數的時候,必須說明成員屬於哪個類。而且從一個模板生成類的名字中必須包含模板的實參。當我們定義一個成員函數的時候,模板實參與模板形參相同。對於一個成員函數,對應blob的成員應該是這個樣子的。
template <typename T>
ret-type Blob<T>::member-name(parm-list)
注意模板的定義和聲明不能分開爲兩個文件,因爲在編譯的時候並不會生成具體類,只有在調用的時候會,所以需要包含.cc,但是這並不是一個好方案,所以還是寫在一個.h文件中比較好
比如一個放在.h中 一個放在.cc中
類模板與另一個模板間的友好關係最常見的形式是建立實例以及友元間的友好關係
//
// Created by root on 20-2-27.
//
#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
#include <vector>
#include <iostream>
// Created by root on 20-2-27.
//
template <typename >class BlobPtr;
template <typename >class Blob;
template <typename T>
bool operator == (const Blob<T>&,const Blob<T>&);
template <typename T>class BlobA{
public:
friend class BlobPtr<T>;
friend bool operator == <T>(const Blob<T>&,const Blob<T>&);
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
BlobA()
{
}
BlobA(std::initializer_list<T> il)
{
for (auto a : il)
{
std::cout<<a<<std::endl;
}
}
int add(T a,T b);
};
template <typename T>
int BlobA<T>::add(T a, T b) {
return a+b;
}
#endif //TEST_TEMPLATE_H
模板類型別名
模板類型的特性,typedef BlobA data2;
另一種方式
希望指定別名的不是一個實例化的模板類,而是一個模板
template <typename T>using partNo = BlobA<unsigned>;
類模板的static成員
與其他任何類都相同,類模板也可以聲明static成員。
template <typename T>class BlobA{
public:
static std::size_t count(){ return ctr;};
static std::size_t ctr;
private:
};
//初始化
template <typename T>size_t BlobA<T>::ctr = 0;
//使用
int main()
{
std::cout<<partNo<int>::count()<<std::endl;
return 0;
}