今天在看《深刻理解C++11》的時候,看到一段有意思的代碼:ios
int (*(*pf())())() { return nullptr; }
我馬上就懵了——歷來沒有見過這樣的函數聲明。那麼它到底是一個怎樣的函數呢?我努力回憶起《C專家編程》一書的內容,把其中解讀變量聲明的方法應用於該函數上,最終讀懂了該函數。下面是大體的解讀過程。編程
首先,要肯定聲明中出現的操做符的優先級。顯然,函數調用操做符()的優先級是高於指針解引用操做符*的。另外,小括號老是具備最高優先級。函數
其次,要肯定在聲明中標識符與某個操做符結合起來的時候有什麼意義。例如:測試
a() a是一個函數
*a a是一個指針spa
因爲函數聲明的特殊性,當指針解引用操做符*與一個表示函數的標識符結合時,表示這個函數的返回值是一個指針。例如 *a() 表示a是一個返回值爲指針的函數。指針
有了以上的基礎,接下來咱們就能夠從聲明中的標識符開始,按照操做符的優先級,由內向外逐步來解讀:code
pf() pf是一個無參數函數 * pf() pf是一個無參數函數,它的返回值是一個指針 ( * pf() ) () pf是一個無參數函數,它的返回值是一個無參數函數的指針 * ( * pf() ) () pf是一個無參數函數,它的返回值是一個無參數函數的指針,這個函數的返回值又是一個指針 ( * ( * pf() ) () ) () pf是一個無參數函數,它的返回值是一個無參數函數的指針,這個函數的返回值又是一個無參數函數的指針 int ( * ( * pf() ) () ) () pf是一個無參數函數,它的返回值是一個無參數函數的指針,這個函數的返回值又是一個無參數且返回值爲int的函數的指針。
最終的解讀結果冗長拗口。能夠看出,這其實是返回值爲函數指針的函數的遞歸聲明。下面是可讀性更強的等效代碼:blog
typedef int (*pa)(); typedef pa (*pb)(); pb pfex() { return nullptr; }
下面是驗證解讀結果的測試代碼。不得不說,測試代碼也不容易理解……遞歸
#include <iostream> int a() { return 29; } int (*b())() { return a; } int (*(*pf())())() { return b; } typedef int (*pa)(); typedef pa (*pb)(); pb pfex() { return b; } int wmain() { int r = pf()()(); std::wcout << r << std::endl; r = pfex()()(); std::wcout << r << std::endl; }
最終的輸出是兩個數字29。io