接上一篇繼續(xù)學(xué)習(xí)抽象類、函數(shù)模板
抽象類
c++中的抽象類是通過純虛函數(shù)體現(xiàn)的,凡是含有純虛函數(shù)的類叫做抽象類
純虛函數(shù):是一種特殊的虛函數(shù)魏保,在許多情況下安岂,在基類中不能對(duì)虛函數(shù)給出有意義的實(shí)現(xiàn)涯雅,而把它聲明為純虛函數(shù),它的實(shí)現(xiàn)留給該基類的派生類去做瘸爽。
它的一般格式如下:
class <類名>{
virtual <類型><函數(shù)名>(<參數(shù)表>)=0;
…
};
抽象類是不能直接創(chuàng)建的您访,如果子類沒有實(shí)現(xiàn)所有的純虛函數(shù),則這個(gè)派生類也是抽象類剪决。
#include <iostream>
#include <string.h>
#include <unistd.h>
using namespace std;
class Human {
private:
int a;
public:
virtual void eating(void) = 0;
virtual void wearing(void) = 0;
virtual void driving(void) = 0;
virtual ~Human() { cout<<"~Human()"<<endl; }
virtual Human* test(void) {cout<<"Human's test"<<endl; return this; }
};
class Englishman : public Human {
public:
void eating(void) { cout<<"use knife to eat"<<endl; }
void wearing(void) {cout<<"wear english style"<<endl; }
void driving(void) {cout<<"drive english car"<<endl; }
virtual ~Englishman() { cout<<"~Englishman()"<<endl; }
virtual Englishman* test(void) {cout<<"Englishman's test"<<endl; return this; }
};
class Chinese : public Human {
public:
void eating(void) { cout<<"use chopsticks to eat"<<endl; }
void wearing(void) {cout<<"wear chinese style"<<endl; }
void driving(void) {cout<<"drive chinese car"<<endl; }
virtual ~Chinese() { cout<<"~Chinese()"<<endl; }
virtual Chinese* test(void) {cout<<"Chinese's test"<<endl; return this; }
};
int main(int argc, char **argv){
//Human h; //抽象類不能直接創(chuàng)建
Englishman e;
Chinese c;
return 0;
}
抽象類主要的作用是進(jìn)行類型隱藏灵汪。構(gòu)造出一個(gè)固定的一組行為的抽象描述,但是這組行為卻能夠有任意個(gè)可能的具體實(shí)現(xiàn)方式柑潦。這個(gè)抽象描述就是抽象類享言,而這一組任意個(gè)可能的具體實(shí)現(xiàn)則表現(xiàn)為所有可能的派生類。
函數(shù)模板
函數(shù)模板不是一個(gè)實(shí)在的函數(shù)渗鬼,編譯器不能為其生成可執(zhí)行代碼览露。定義函數(shù)模板后只是一個(gè)對(duì)函數(shù)功能框架的描述,當(dāng)它具體執(zhí)行時(shí)譬胎,將根據(jù)傳遞的實(shí)際參數(shù)決定其功能差牛。類似java中的泛型命锄。
函數(shù)模板定義的一般形式如下:
template<類型形式參數(shù)表>
返回類型 函數(shù)名(形式參數(shù)表){
... //函數(shù)體
}
使用模板實(shí)現(xiàn)返回2個(gè)數(shù)中大值函數(shù)
#include <iostream>
#include <string.h>
#include <unistd.h>
using namespace std;
template<typename T>
T& mymax(T& a, T& b){
cout<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}
int main(int argc, char **argv){
int ia = 1, ib = 2;
float fa = 1, fb = 2;
double da = 1, db = 2;
mymax(ia, ib);
mymax(fa, fb);
mymax(da, db);
return 0;
}
cout<<PRETTY_FUNCTION<<endl;可以打印方法名稱
輸出:
T& mymax(T&, T&) [with T = int]
T& mymax(T&, T&) [with T = float]
T& mymax(T&, T&) [with T = double]
- 函數(shù)模板的原理:
- 函數(shù)模板只是編譯指令,一般寫在頭文件中偏化;
- 編譯程序時(shí)脐恩,編譯器根據(jù)函數(shù)的參數(shù)來“推導(dǎo)”模板的參數(shù);然后生成具體的模板函數(shù)
示例代碼:
int a; int b; mymax(a, b);
編譯器根據(jù)函數(shù)參數(shù)a,b推導(dǎo)出模板參數(shù)為int侦讨,所以把模板中的T綁定為int被盈;
編譯程序時(shí)生成如下函數(shù):
int& mymax(int& a, int& b){
return (a<b)?b:a;
}
所以在上面的main函數(shù)中有int、float搭伤、double三種類型的模板函數(shù)。
mymax(ia, ib);
mymax(fa, fb);
mymax(da, db);
這三個(gè)的調(diào)用其實(shí)調(diào)用了三個(gè)模板函數(shù)
模板的參數(shù)推導(dǎo)支持的類型轉(zhuǎn)換比較少袜瞬,主要有兩種:
- const轉(zhuǎn)換 :函數(shù)參數(shù)為非const引用/指針, 它可以隱式轉(zhuǎn)換為const引用/指針
template<typename T>
const T& mymax(const T& a, const T& b){
cout<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}
int main(int argc, char **argv){
int ia = 1;
int ib = 2;
mymax(ia, ib);
return 0;
}
推導(dǎo)的結(jié)果:const T& mymax(const T&, const T&) [with T = int]
- 數(shù)組或函數(shù)指針轉(zhuǎn)換:
- 1.數(shù)組可以隱式轉(zhuǎn)換為“指向第1個(gè)元素的指針”
- 2.參數(shù)為“函數(shù)的名字” 時(shí)怜俐,它隱式轉(zhuǎn)換為“函數(shù)指針”
template<typename T>
const T& mymax(const T& a, const T& b){
cout<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}
template<typename T>
const T* mymax2(const T* a, const T* b){
cout<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}
template<typename T>
void test_func(T f){
cout<<__PRETTY_FUNCTION__<<endl;
}
int f1(int a, int b){
return 0;
}
int main(int argc, char **argv){
char a[]="ab";
char b[]="cd";
mymax(a, b); /* T=char[3] */
mymax2(a, b);
char a2[]="abc";
char b2[]="cd";
//mymax(a2, b2); /* mymax(char[4], char[3]), 無法推導(dǎo)出T: mymax(char& [4], char& [3]), 因?yàn)閮蓚€(gè)參數(shù)類型不一樣 */
mymax2(a2, b2); /* mymax2(char[4], char[3]), 推導(dǎo): mymax2(const char *, const char *); */
test_func(f1);
test_func(&f1);
return 0;
}
輸出:
const T& mymax(const T&, const T&) [with T = char [3]]
const T* mymax2(const T*, const T*) [with T = char]
const T* mymax2(const T*, const T*) [with T = char]
void test_func(T) [with T = int (*)(int, int)]
void test_func(T) [with T = int (*)(int, int)]
mymax2模板可以將數(shù)組轉(zhuǎn)換為指針,所以char數(shù)組的長度不同也會(huì)推導(dǎo)出來是 char*,而如果是引用則會(huì)因?yàn)橥茖?dǎo)出char& [4], char& [3]不一樣的類型邓尤,推導(dǎo)失敗拍鲤。
對(duì)于傳入的參數(shù)是函數(shù),不論是函數(shù)名還是引用汞扎,都會(huì)被轉(zhuǎn)為函數(shù)指針季稳。