自適應網(wǎng)站制作類似互推商盟的推廣平臺
模板
C++提供了模板(template)編程的概念。所謂模板,實際上是建立一個通用函數(shù)或類, 其類內(nèi)部的類型和函數(shù)的形參類型不具體指定 ,用一個虛擬的類型來代表。這種通用的方式稱為模板。 模板是泛型編程的基礎, 泛型編程即以一種獨立于任何特定類型的方式編寫代碼如: vector
函數(shù)模板(可以嵌套使用)
模板函數(shù)就是函數(shù)模板的自動實現(xiàn)
功能:使用函數(shù)體相同的函數(shù)都可以用這個模板替代實現(xiàn)多個函數(shù)用來返回兩個數(shù)的最大值,要求能支持 char 類型、int 類型、doubletemplate <typename T>如:template <typename T>//這里的類屬參數(shù) T在下面函數(shù)體的 參數(shù)中必須出現(xiàn)一次
????????T Max(T a, T b) {
?? ?????????return a > b ? a : b;
????????}形式:cout << Max(a, b) << endl;//編譯器自動推導類型
cout << Max<int>(a,b)<<endl;//顯示類型調(diào)用

#include <iostream>
using namespace std;template <typename T>
T Max(T a, T b) {return a > b ? a : b;
}
int main(void) {int a = 4;int b = 5;float x = 1.2f;float y = 2.6f;cout << Max(a, b) << endl;//編譯器自動推導類型cout << Max<int>(a,b)<<endl;//顯示類型調(diào)用cout << Max(x, y) << endl;return 0;
}
函數(shù)模板和函數(shù)重載
//當函數(shù)模板和普通函數(shù)都符合調(diào)用時,優(yōu)先選擇普通函數(shù)//Max(a,b);//如果 顯式指定類型 的使用函數(shù)模板,則使用<> 類型列表//Max<>(a, b);//如果函數(shù)模板會產(chǎn)生更好的匹配,使用函數(shù)模板
?函數(shù)模板的調(diào)用機制
函數(shù)模板在調(diào)用的時候,會根據(jù)調(diào)用者的數(shù)據(jù)類型,創(chuàng)建一個匹配的函數(shù)
類模板
類模板和函數(shù)模板一致
在類使用數(shù)據(jù)類型的地方都可以用模板的類屬參數(shù)進行替換
(成員數(shù)據(jù)的數(shù)據(jù)類型,構造函數(shù)的參數(shù)類型,成員函數(shù)的返回值類型)
注:在模板類定義對象的時候必須指定為顯示指定類型<>
當為單個參數(shù)時:
#include <iostream>
using namespace std;
template <typename T>
class A {
public:A(T a) {this->a = a;}T getA() {return a;}
private:T a;
};int main(void) {A<int> aa(666);cout << aa.getA() << endl;return 0;
}
當為多個參數(shù)時
#include <iostream>
using namespace std;
template <typename T1,typename T2>
class A {
private:T1 a;T2 b;
public:A(T1 a ,T2 b) {this->a = a;this->b = b;}T1 getA() {return a;}T2 getB() {return b;}
};int main(void) {A<int, double> aa(12,4.5);cout << aa.getA() << endl;cout << aa.getB() << endl;return 0;
}
當類作為函數(shù)參數(shù)的時候
?double add(A<int, double>& a) {
?? ?double sum = 0;
?? ?sum = a.getA() + a.getB();
?? ?return sum;
}
當子類繼承父類(父類為模板類時)
?class B :public A<int, double> {
?? ?B(int a, double b):A(a,b) {}
};
當子類是模板類,父類是一般類時?
?和普通繼承一樣
#include <iostream>
using namespace std;class B {
protected:int a;double b;
public:B(int a=1, double b=1.2) {this->a = a;this->b = b;}
};template <typename T1, typename T2>
class A :public B{
public:A();A(T1 a, T2 b) :B(a, b) {}T1 getA() {return a;}T2 getB() {return b;}
};double add(A<int, double>& a) {double sum = 0;sum = a.getA() + a.getB();return sum;
}
int main(void) {A<int ,double> aa(12,12.2);cout << aa.getA() << endl;cout << aa.getB() << endl;return 0;
}
當子類和父類都是模板類
和普通繼承一樣
#include <iostream>
using namespace std;template <typename T1, typename T2>
class B {
public:B(T1 a, T2 b){this->a = a;this->b = b;}T1 getA() {return a;}T2 getB() {return b;}
protected:T1 a;T2 b;
};template <typename T1, typename T2>
class A :public B<int, double>{
public:A();A(T1 a, T2 b) :B(a, b) {}T1 getA() {return a;}T2 getB() {return b;}
};double add(A<int, double>& a) {double sum = 0;sum = a.getA() + a.getB();return sum;
}
int main(void) {A<int, double> aa1(10, 10.2);cout << aa1.getA() << endl;cout << aa1.getB() << endl;A<int ,double> aa(12,12.2);cout << aa.getA() << endl;cout << aa.getB() << endl;return 0;
}
類模板和友元函數(shù)?
(1) 類內(nèi)部聲明友元函數(shù),必須寫成一下形式template < typename T>friend A<T> addA (A<T> &a, A<T> &b);(2) 友元函數(shù)實現(xiàn) 必須寫成template < typename T>A<T> add(A<T> &a, A<T> &b) {????????//......}(3) 友元函數(shù)調(diào)用 必須寫成A< int > c4 = addA <int> (c1, c2);
?類模板的封裝
這里僅分為兩個文件(.h和.cpp+main.cpp)
函數(shù)前聲明 template< 類型形式參數(shù)表 >類的成員函數(shù)前的 類限定域說明必須要帶上虛擬參數(shù)列表template<typename T1>
A<T1>::A(T1 a)
{
?? ?this->a = a;
}返回的變量是模板類的對象時必須帶上虛擬參數(shù)列表T1 A<T1>::getA() {
?? ?return a;
}成員函數(shù)參數(shù)中出現(xiàn)模板類的對象時必須帶上虛擬參數(shù)列表(也可以不帶)A<T1> A<T1>::operator+( const A<T1> & other)
{
?? ?A<T1> tmp = this->a + other.a;
?? ?return tmp.a;
}成員函數(shù)內(nèi)部沒有限定( 可帶可以不帶 )A<T1> A<T1>::operator+( const A<T1> & other)
{
?? ?A<T1> tmp = this->a + other.a;
?? ?return tmp.a;
}
類模板封裝單參:?
.h
#include <iostream>
using namespace std;template <typename T1>
class A {
public:A(T1 a);T1 getA();A operator+(const A& other);void print();
private:T1 a;
};.cpp
#include <iostream>
using namespace std;
#include "A.h"template<typename T1>
A<T1>::A(T1 a)
{this->a = a;
}
template <typename T1>
T1 A<T1>::getA() {return a;
}
template<typename T1>
A<T1> A<T1>::operator+(const A& other)
{A tmp = this->a + other.a;return tmp.a;
}template<typename T1>
void A<T1>::print()
{cout << this->a << endl;
}
int main(void) {A<int> a(12);A<int> b(11);A<int> c = a + b;c.print();return 0;
}
?這里僅分為三個文件(.h 和? .cpp? 和? main.cpp)
如果分為這三個文件,那么只包含.h頭文件就會報錯C++ 類模板“無法解析的外部符號
在封裝有三個文件的時候mian.cpp中就不用包含.h頭文件了,僅包含.cpp文件即可
#include <iostream>
using namespace std;//#include "A.h"//同時包含兩個或者僅包含.h都會報錯
#include "A.cpp"int main(void) {
?? ?A<int> a(12);
?? ?A<int> b(11);
?? ?A<int> c = a + b;
?? ?c.print();
?? ?return 0;
}
類模板封裝多參
算術運算符重載多參
template<typename T1, typename T2>
A1<T1, T2> A1<T1, T2>::operator+(const A1<T1,T2>& other)
{
? ? A1<T1, T2> tmp{ this->a + other.a,this->b + other.b };
? ? return tmp;
}?輸出運算符重載多參
template<typename T1, typename T2>
friend ostream& operator<<(ostream& os, const A1<T1, T2>& other);//設置為友元template<typename T1, typename T2>
ostream& operator<<(ostream& os, const A1<T1, T2>& other)
{
? ? //“T1 A1<T1,double>::getA(void)”:?
? ? // 不能將“this”指針從“const A1<int,double>”轉換為“A1<int,double>?
? ? //是因為傳入的是const引用,但是調(diào)用了非const方法。
? ? os << other.getA() << " " << other.getB() << endl;
? ? //os << other.a <<" " << other.b << endl;
? ? return os;
}
?.h
#pragma once#include <iostream>
using namespace std;template <typename T1, typename T2>
class A1 {
public:A1(T1 a, T2 b);T1 getA()const;T2 getB()const;A1<T1, T2> operator+(const A1& other);template<typename T1, typename T2>friend ostream& operator<<(ostream& os, const A1<T1, T2>& other);
public:T1 a;T2 b;
};template<typename T1, typename T2>
ostream& operator<<(ostream& os, const A1<T1, T2>& other)
{os << other.getA() << " " << other.getB() << endl;//os << other.a <<" " << other.b << endl;return os;
}
?.cpp
#include "A1.h"
#include <iostream>
using namespace std;
template<typename T1, typename T2>
A1<T1, T2>::A1(T1 a, T2 b):a(a),b(b)
{
}
template <typename T1, typename T2>
T1 A1<T1, T2>::getA() const{return a;
}
template<typename T1, typename T2>
T2 A1<T1, T2>::getB()const {return b;
}template<typename T1, typename T2>
A1<T1, T2> A1<T1, T2>::operator+(const A1<T1,T2>& other)
{A1<T1, T2> tmp{ this->a + other.a,this->b + other.b };return tmp;
}
主函數(shù)
#include <iostream>
#include "A1.cpp" //這里不要包含錯了
int main(void) {A1<int, double> a(12, 3.3), b(13, 32.9);A1<int, double> c = a + b;cout << c << endl;return 0;
}
?
?類模板的靜態(tài)成員數(shù)據(jù)
? 從類模板實例化的每個模板類有自己的類模板數(shù)據(jù)成員,該 模板類的所有對象共享一個 static 數(shù)據(jù)成員和非模板類的 static 數(shù)據(jù)成員一樣, 模板類的 static 數(shù)據(jù)成員也應該在文件范圍定義和初始化? static 數(shù)據(jù)成員也可以使用虛擬類型參數(shù) T
public:
????????static T1 count;
//初始化靜態(tài)成員數(shù)據(jù)
template<typename T1>
T1 A<T1>::count = 66;//通過對象a對靜態(tài)count賦值后
cout << a.count << endl;
a.count = 888;
cout << b.count << endl;
b.count = 1000;
cout << a.count << endl;?