準確地講,本文所涉及的內容是C++中較難理解的,本文的目的不是在于將它們解釋清楚,因為這需要你循序漸進地做很多練習才可以??聪旅嬉粋€例子:
int
(*func(
bool
real))(
int
,
int
)
你覺得它的返回值是什么?
這里就涉及到了如何理解指向函數的指針的問題了。一些來自C++教材的建議是從里向外解讀這個表達式,這里所謂的里面就是func(bool real),那么剩下的部分就是所謂的返回值了?有點生硬吧。下面就讓我們循序漸進地看看如何理解更好?
為什么會對這個表達式的返回值產生疑問?
要解決問題通常需要找出問題所在,這里是基于這樣一種思維定勢,那就是我們通常習慣于這樣一種聲明變量的方式:
int a;
這里我們聲明a是一個int類型的變量。而對于返回值,我們通常也是采用類似的方式,如一個返回值為int類型的函數通??梢砸韵旅娴姆绞竭M行聲明:
int func([params]);
因此我們慣性地認為返回值就是最左側的一個類型名,雖然這通常是對的,但是針對上面的那個例子則顯得十分尷尬。
讓我們看看一個指向函數的指針的聲明式:
int
(*
pCompare)(
int
,
int
);
這個指針的名字就是pCompare,令人奇怪的是pCompare并不是在整個聲明式的最右邊,類型也肯定不是int,而是一個復雜的表達式。讓我們用typedef來聲明就會發現typedef的使用也不太一樣。
typedef int
(*
PF
)(
int
,
int
);
我們發現跟慣用的typedef *** ???;的方式也截然不同,在上面這個typedef過后,整個表達式可以被簡化成:
PF pCompare;
現在我們似乎就一見如故了,現在的表達式看起來中規中矩,普通的聲明都是類型名加變量名完成聲明,而函數指針的聲明則是在一個表達式中一個固定的位置進行聲明。
?
int
(*
)(
int
,
int
);
在上文中劃線的部分即為聲明的部分,也就是這點不同讓我們逐漸迷失了方向。
現在讓我們寫一個返回指向函數的指針的函數,也就是返回值是PF的函數,這就像我們從返回int類型的變量到返回int類型值的函數一樣,因此使用以下方式即可:
PF func([params]);
現在讓我們擴展PF,將它還原,也就是把右側的func([params])部分移到那個橫線的位置上?,F在我們就可以很輕松地理解本文開頭的那個函數,原來是返回值為int (*)(int, int)的函數
int
(*func(
bool
real))(
int
,
int
)
以上劃線的部分也就是一個函數扣除返回值的部分。也就等價于
PF
func(
bool
real)
至此你應該能夠分析更加復雜的表達式了。
下面的示例旨在幫助理解本文:
/*
?*?main.cc
?*
?*??Created?on:?2009-2-1
?*??????Author:?Volnet
?
*/
#include?
<
stdlib.h
>
#include?
<
iostream
>
using
?std::cout;
using
?std::endl;
int
?myCompare1(
????????
int
?a,?
int
?b,
????????
int
?(
*
Compare)(
int
,?
int
));
int
?realCompare(
int
?a,?
int
?b);
int
?fakeCompare(
int
?a,?
int
?b);
typedef?
int
?(
*
PF)(
int
,?
int
);
int
?myCompare2(
????????
int
?a,?
int
?b,
????????PF?Compare);
PF?getAPointerFunc1(
bool
?real);
int
?(
*
getAPointerFunc2(
bool
?real))(
int
,?
int
);
int
?main(
void
){
????
int
?typeDeclared;
????typeDeclared?
=
?
1
;
????
//
PF?pCompare;
????
int
?(
*
pCompare)(
int
,?
int
);
????
if
(pCompare?
==
?NULL)
????????cout
<<
"
pCompare?==?NULL
"
<<
endl;
????
else
????{
????????cout
<<
"
pCompare?!=?NULL
"
<<
"
?pComapre?=?
"
<<
pCompare
<<
endl;
????}
????cout
<<
"
Compare?the?pointer?function.
"
<<
endl;
????cout
<<
"
The?compare?result?is?:?
"
<<
????????myCompare1(
6
,?
5
,?realCompare)
<<
endl;
????cout
<<
"
It's?the?same?to?invoke?realCompare?&?*realCompare?:?
"
<<
????????myCompare1(
6
,?
5
,?
*
realCompare)
<<
endl;
????cout
<<
"
Using?the?typedef?to?predigest?definition?:?
"
<<
????????myCompare2(
8
,?
7
,?realCompare)
<<
endl;
????cout
<<
"
Return?a?pointer?from?a?function?:?
"
<<
????????myCompare2(
10
,?
20
,?getAPointerFunc1(
true
))
<<
endl;
????cout
<<
"
Return?a?pointer?from?a?function?:?
"
<<
????????myCompare2(
20
,?
30
,?getAPointerFunc2(
false
))
<<
endl;
????
return
?EXIT_SUCCESS;
}
int
?myCompare1(
????????
int
?a,?
int
?b,
????????
int
?(
*
Compare)(
int
,?
int
)){
????
return
?Compare(a,?b);
}
int
?realCompare(
int
?a,?
int
?b){
????cout
<<
"
The?realCompare?has?be?invoked.
"
<<
endl;
????
if
(a?
==
?b)
????????
return
?
0
;
????
if
(a?
<
?b)
????????
return
?
-
1
;
????
else
????????
return
?
1
;
}
int
?fakeCompare(
int
?a,?
int
?b){
????cout
<<
"
The?fackCompare?has?be?invoked.
"
<<
endl;
????
return
?
200
;
}
int
?myCompare2(
????????
int
?a,?
int
?b,
????????PF?Compare){
????
return
?Compare(a,?b);
}
PF?getAPointerFunc1(
bool
?real){
????
if
(real)
????????
return
?realCompare;
????
else
?
return
?fakeCompare;
}
int
?(
*
getAPointerFunc2(
bool
?real))(
int
,?
int
){
????
if
(real)
????????
return
?realCompare;
????
else
?
return
?fakeCompare;
}
?