int (*(*pf())())() { return nullptr; }
從來沒有見過這樣的函數聲明。那么它究竟是一個怎樣的函數呢?我努力回憶起《C專家編程》一書的內容,把其中解讀變量聲明的方法應用於該函數上,最終讀懂了該函數。下面是大致的解讀過程。
首先,要確定聲明中出現的操作符的優先級。顯然,函數調用操作符()的優先級是高於指針解引用操作符*的。另外,小括號總是具有最高優先級。
其次,要確定在聲明中標識符與某個操作符結合起來的時候有什么意義。例如:
a() a是一個函數
*a a是一個指針
由於函數聲明的特殊性,當指針解引用操作符*與一個表示函數的標識符結合時,表示這個函數的返回值是一個指針。例如 *a() 表示a是一個返回值為指針的函數。
有了以上的基礎,接下來我們就可以從聲明中的標識符開始,按照操作符的優先級,由內向外逐步來解讀:
pf() pf是一個無參數函數 * pf() pf是一個無參數函數,它的返回值是一個指針 ( * pf() ) () pf是一個無參數函數,它的返回值是一個無參數函數的指針 * ( * pf() ) () pf是一個無參數函數,它的返回值是一個無參數函數的指針,這個函數的返回值又是一個指針 ( * ( * pf() ) () ) () pf是一個無參數函數,它的返回值是一個無參數函數的指針,這個函數的返回值又是一個無參數函數的指針 int ( * ( * pf() ) () ) () pf是一個無參數函數,它的返回值是一個無參數函數的指針,這個函數的返回值又是一個無參數且返回值為int的函數的指針。
最終的解讀結果冗長拗口。可以看出,這實際上是返回值為函數指針的函數的遞歸聲明。下面是可讀性更強的等效代碼:
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; }