王玉山
(廣東外語外貿(mào)大學,廣州 510440)
一個難于理解的C++函數(shù)指針問題
王玉山
(廣東外語外貿(mào)大學,廣州 510440)
摘要:指針是C、C++程序設計語言中一個比較復雜、難于掌握的概念。但又是任何一個C、C++程序設計者必須過的一道門檻。本文只就其中比較難難于理解的函數(shù)指針的一個例子加以闡述。希望對于C、C++程序設初學者有所幫助。
關鍵詞:C++程序設計;C++函數(shù)指針;
指針常量與指針變量統(tǒng)稱為指針。有關變量(類對象)、數(shù)組、函數(shù)、字符串常量的地址值都是地址常量,它們不能被賦值,只能做右值;可以被賦值的地址變量是指針變量,它們可以做左值也可以作右值。
函數(shù)名是函數(shù)代碼段的入口地址,是地址常量,只能做右值;指向函數(shù)的指針變量是用來存放函數(shù)的入口地址的,可以做左值也可以做右值。
象普通變量賦值一樣,函數(shù)指針變量的賦值要求右值和左值必須類型一致。什么是函數(shù)指針的類型呢?就是在定義函數(shù)指針時,我們把指針名去掉,剩下的部分就是函數(shù)指針的類型。
int (*return_fun(char op))(int, int){……}。去掉return_fun(char op)后留下部分為:int (*)(int, int),即為函數(shù)return_fun(char op)返回的類型,是一個返回值為整形,有2個整形參數(shù)的函數(shù)。它的形參是字符變量char op。
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a + b;}
int sub(int a,int b)
{
return a-b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return b?a/b:-1;
}
下面定義的return_fun(char op),即為返回指向函數(shù)的指針函數(shù),該函數(shù)參數(shù)是char op。
int (*return_fun(char op))(int, int)
{
switch (op)
{
case '+':return add;//返回函數(shù)的地址,即函數(shù)名。
case '-':return sub;
case '*':return mul;
case '/':return div;
default:
return NULL;
}
}
//s_fp為指向函數(shù)的指針變量,指向有2個整形參數(shù),返回值為整形的函數(shù)。 這里指向函數(shù)的指針變量 s_fp的右值是:return_ fun(op),return_fun(op)是一個函數(shù)調(diào)用、返回一個函數(shù)指針常量,即四個函數(shù)名add、sub、mul、div之一。
//下面的語句根據(jù)上一步得到的函數(shù)的地址調(diào)用相應函數(shù),并返回運算結果。
if (s_fp)return s_fp(a, b);
else return -1;
}
int main(int argc, char** argv){
int a = 800, b = 200;
cout<<a<<"+"<<b<<"="<<calc(a,'+', b )<<endl;
cout<<a<<"-"<<b<<"="<<calc(a, '-', b)<<endl;
cout<<a<<"*"<<b<<"="<<calc(a, '*',b)<<endl;
cout<<a<<"/"<<b<<"="<<calc(a,'/', b )<<endl;
return 0;
}
以上程序在DevC++5.4.2版本下通過試驗。
指向函數(shù)的指針,定義的時候為了保證類型一致,少犯錯誤。可以把函數(shù)定義的頭部搬到定義的地方,在后面加上分號,把原來的函數(shù)名換為合法的標示符。如有函數(shù):int add(int a, int b){return a + b;}。我們就把這個函數(shù)頭部的函數(shù)名用Psum代替、省掉參數(shù)名、將標示符左側加*號,必須將*號與標示符加括號進行綁定得到:int (* Psum )(int , int);此時Psum就是可以指向int add(int a, int b){return a + b;}函數(shù)的指針變量了。注意這個用于綁定的括號絕對不能省掉,如果省掉Psum就不是變量了!成了這樣:int * Psum (int , int);這就成了返回整形指針的函數(shù)原形聲明了。Psum也成了常量。
象普通變量一樣,指向函數(shù)的指針變量也必須先定義后使用。
前面函數(shù)頭部為:int (*return_fun(char op))(int, int)的例子中,是一個比較復雜的應用,該代碼段定義的函數(shù)為return_fun(char op),而函數(shù)return_fun(char op))的返回類型是int (*return_fun(char op))(int,int)中把return_fun(char op)去掉后留下的部分:int (*)(int, int),這是一個指向函數(shù)的指針類型。在本例中最右側的括號(int, int)是絕對不能省掉的,因為它是確定return_fun(char op)返回類型的關鍵。
再看以下代碼段:void (*setF1(void (*f)()))(){……}。我們該如何理解?當然要從setF1為起點,右邊的括號有幾個,這看起來讓人有點頭暈。這里要特別注意圓括號的運算級別和結合性,我們知道圓括號的優(yōu)先級是1級,左結合性。而這里的*號是間接訪問運算符,優(yōu)先級是1級。所以應該先有setF1(void (*f)()),它是一個整體,setF1()的參數(shù)是void (*f)(),是一個指向函數(shù)的指針參數(shù),在void (*setF1(void (*f)()))()中,把setF1(void (*f)())去掉后留下的部分是void (*)()就是函數(shù)setF1的返回類型。
參考文獻:
[1]王珊珊等著.C++程序設計教程(第2版),北京:機械工業(yè)出版社,2011年1月第 2 版,ISBN978-7-111-33022-6.
[2]譚浩強著.C程序設計,第三版,北京, 清華大學出版社,2005年 7月第3 版,ISBN 7-302-10853- 6/TP·7217.
[3]史上最牛逼的 C++指針 http://wenku.baidu.com/link?url=Mw5lETdR_tZo2-6zbkNmj7pZPb7OiiYPzwrvO0epmv6SAX14UFJ Yq9u3xt5gPwOlM8u1ZKlscq2U-SfUk6GshQooN59vaVJxJAo8YxLDWuy.