C++中的多型(雖然多型不是C++所特有的,但是C++中的多型確實是很特殊的)分為靜多型和動多型(也就是靜態繫結和動態繫結兩種現象),靜動的區別主要在於這種繫結發生在編譯期還是執行期,發生在編譯期的是靜態繫結,也就是靜多型;發生在執行期的則是動態繫結,也就是動多型。
靜多型可以透過模板和函式過載來實現(之所說C++中的多型主要還是因為模板這個東西),下面舉兩個例子:
1)函式模板
template<typenameT>
Tmax(constT&lsh,constT&rhs)
{
return(lsh>rhs)?lsh:rhs;
}
返回兩個任意型別物件的最大值(物件),前提是該型別能夠使用>運算子進行比較,並且返回值是bool型別。
使用:
inta=3;intb=4;
cout<<max(a,b)<<endl;
floatc=2.4;floatd=1.2;
cout<<max(c,d)<<endl;
輸出結果為:
4
2.4
這種繫結發生在編譯期,這是由於模板的例項化是發生在編譯期的,即在編譯時編譯器發現你呼叫max(a,b)時就自動生成一個函式
intmax(constint&lsh,constint&rhs)
即將所有的T替換成int;
當你呼叫max(c,d)時就自動生成一個函式
floatmax(constfloat&lsh,constfloat&rhs)
之所以說開始的函式定義是函式模板,就是因為他就像個模子似的,你可以用鋁作為原料也可以用石膏或者銅。
2)函式過載:
intmax(inta,intb)
return(a>b)?a:b;
intmax(inta,intb,intc)
returnmax(max(a,b),c);
兩個函式名稱一樣,引數型別或個數不完全相同,返回值一樣(這個不重要)。
inta=3,b=4,c=5;
cout<<max(a,b,c)<<endl;
5
確定函式的過程也發生在編譯器,當你使用max(a,b),編譯器發現只有兩個引數,那麼就呼叫只有兩個引數的函式版本,當使用max(a,b,c)時,編譯器則使用有3個引數的版本。
透過上面的兩個例子,你還可以使用更為方便的模板函式過載:
Tmax(constT&a,constT&b,constT&c)
使用
floata=3.6,b=1.2,c=7.8;
輸出:
7.8
透過引數個數和型別,編譯器自動生成和呼叫對應得函式版本!
動多型則是透過繼承、虛擬函式(virtual)、指標來實現。
classA{
public:
virtualvoidfunc()const{
coust<<“A::func()”<<endl;
classB:publicA{
coust<<“B::func()”<<endl;
Aa*=B();
a->func();
B::func()
編譯期是不呼叫任何函式的,編譯器編譯到a->func()時只是檢查有沒有語法問題,經過檢查沒有。編譯器並不知道呼叫的是A版本的func()還是B版本的func(),由於a是一個指向B物件的指標,所以a只知道它指向的是一個A型別(或者能轉換成A型別)的物件。通常整合體系就說明了(由於是公有繼承)B是一種A。在執行期,a要呼叫a所指向物件的func()函式,就對它指向的物件下達呼叫func()的命令,結果a所指向的是一個B物件,這個物件就呼叫了自己版本(B版)的func()函式,所以輸出時B::func()
總結:
在編譯期決定你應該呼叫哪個函式的行為是靜態繫結(static-binding),這種現象就是靜多型。
在執行期決定應該呼叫哪中型別物件的函式的行為是動態繫結(dynamic-binding),這種現象就是動多型
C++中的多型(雖然多型不是C++所特有的,但是C++中的多型確實是很特殊的)分為靜多型和動多型(也就是靜態繫結和動態繫結兩種現象),靜動的區別主要在於這種繫結發生在編譯期還是執行期,發生在編譯期的是靜態繫結,也就是靜多型;發生在執行期的則是動態繫結,也就是動多型。
靜多型可以透過模板和函式過載來實現(之所說C++中的多型主要還是因為模板這個東西),下面舉兩個例子:
1)函式模板
template<typenameT>
Tmax(constT&lsh,constT&rhs)
{
return(lsh>rhs)?lsh:rhs;
}
返回兩個任意型別物件的最大值(物件),前提是該型別能夠使用>運算子進行比較,並且返回值是bool型別。
使用:
inta=3;intb=4;
cout<<max(a,b)<<endl;
floatc=2.4;floatd=1.2;
cout<<max(c,d)<<endl;
輸出結果為:
4
2.4
這種繫結發生在編譯期,這是由於模板的例項化是發生在編譯期的,即在編譯時編譯器發現你呼叫max(a,b)時就自動生成一個函式
intmax(constint&lsh,constint&rhs)
{
return(lsh>rhs)?lsh:rhs;
}
即將所有的T替換成int;
當你呼叫max(c,d)時就自動生成一個函式
floatmax(constfloat&lsh,constfloat&rhs)
{
return(lsh>rhs)?lsh:rhs;
}
之所以說開始的函式定義是函式模板,就是因為他就像個模子似的,你可以用鋁作為原料也可以用石膏或者銅。
2)函式過載:
intmax(inta,intb)
{
return(a>b)?a:b;
}
intmax(inta,intb,intc)
{
returnmax(max(a,b),c);
}
兩個函式名稱一樣,引數型別或個數不完全相同,返回值一樣(這個不重要)。
使用:
inta=3,b=4,c=5;
cout<<max(a,b)<<endl;
cout<<max(a,b,c)<<endl;
輸出結果為:
4
5
確定函式的過程也發生在編譯器,當你使用max(a,b),編譯器發現只有兩個引數,那麼就呼叫只有兩個引數的函式版本,當使用max(a,b,c)時,編譯器則使用有3個引數的版本。
透過上面的兩個例子,你還可以使用更為方便的模板函式過載:
template<typenameT>
Tmax(constT&lsh,constT&rhs)
{
return(lsh>rhs)?lsh:rhs;
}
template<typenameT>
Tmax(constT&a,constT&b,constT&c)
{
returnmax(max(a,b),c);
}
使用
floata=3.6,b=1.2,c=7.8;
cout<<max(a,b,c)<<endl;
輸出:
7.8
透過引數個數和型別,編譯器自動生成和呼叫對應得函式版本!
動多型則是透過繼承、虛擬函式(virtual)、指標來實現。
classA{
public:
virtualvoidfunc()const{
coust<<“A::func()”<<endl;
}
}
classB:publicA{
public:
virtualvoidfunc()const{
coust<<“B::func()”<<endl;
}
}
使用:
Aa*=B();
a->func();
輸出:
B::func()
編譯期是不呼叫任何函式的,編譯器編譯到a->func()時只是檢查有沒有語法問題,經過檢查沒有。編譯器並不知道呼叫的是A版本的func()還是B版本的func(),由於a是一個指向B物件的指標,所以a只知道它指向的是一個A型別(或者能轉換成A型別)的物件。通常整合體系就說明了(由於是公有繼承)B是一種A。在執行期,a要呼叫a所指向物件的func()函式,就對它指向的物件下達呼叫func()的命令,結果a所指向的是一個B物件,這個物件就呼叫了自己版本(B版)的func()函式,所以輸出時B::func()
總結:
在編譯期決定你應該呼叫哪個函式的行為是靜態繫結(static-binding),這種現象就是靜多型。
在執行期決定應該呼叫哪中型別物件的函式的行為是動態繫結(dynamic-binding),這種現象就是動多型