天天看點

C++:17---函數指針

一、格式

  • 指針名前*号,并且将*和指針名用括号括起來

例如:

  1. //指針名為pf,指向一個傳回值為bool,參數為兩個const string&的函數
  2. bool (*pf)(const string&, const string&);
  3. //這個不是函數指針,而是一個傳回值為bool*的pf函數
  4. bool *pf(const string&, const string&);

二、函數指針的指派

  • 可以直接将函數名指派給函數指針,或者在函數名前加&符号都可以
  1. bool lengthCompare(const string&, const string&);
  2. bool (*pf)(const string&, const string&);
  3. int main()
  4. {
  5. pf = lengthCompare; //正确
  6. pf = &lengthCompare;//正确
  7. return 0;
  8. }

三、通過函數指針調用函數

調用方式

  • 如果pf是一個函數指針,那麼*pf就是該指針所指向的函數,是以(*pf)()就是調用該函數
  • ANSI C标準允許程式員将(*pf)()簡寫為pf(),但是一定要記住這種寫法是一種簡寫形式

示範案例 

  1. bool lengthCompare(const string&, const string&);
  2. bool (*pf)(const string&, const string&);
  3. int main()
  4. {
  5. pf = lengthCompare;
  6. bool b1 = (*pf)("hello", "goodbye");//相當于在調用lengthCompare("hello","goodbye")
  7. bool b2 = pf("hello","goodbye"); //同上,但是注意這是簡寫形式
  8. return 0;
  9. }

四、函數指針的注意事項

  • 函數指針可以指派為空或者0
  • 函數指針必須指向與指針傳回值類型以及參數相同的函數

五、重載函數的指針

  • 定義一個重載函數指針時,必須有相對應比對的重載函數與指針比對
  1. void ff(int*);
  2. void ff(unsigned int);
  3. void (*pf)(int*)=ff; //正确,指向void ff(int*);
  4. void (*pf2)(int)=ff; //錯誤,沒有比對的函數
  5. double (*pf3)(unsigned in)=ff; //錯誤,沒有比對的函數

六、函數/函數指針傳參

  • 一個函數的形參為函數或者函數指針時,調用這個函數時,函數形參可以為函數本身也可以為函數指針(調用時本質上傳入的都是函數的指針)
  1. bool lengthCompare(const string&, const string&);
  2. void useBigger(const string&, const string&, bool pf(const string&, const string&));
  3. void useBigger2(const string&, const string&, bool (*pf)(const string&, const string&));
  4. int main()
  5. {
  6. bool (*pf)(const string&, const string&);
  7. pf = lengthCompare;
  8. useBigger("hello", "goodbye",lengthCompare);
  9. useBigger("hello", "goodbye", pf);
  10. useBigger2("hello", "goodbye", lengthCompare);
  11. useBigger2("hello", "goodbye", pf);
  12. return 0;
  13. }

七、函數與函數指針取别名

  • 可以使用typedef和decltype來簡化函數或函數指針的聲明
  • 注意:decltype傳回的是函數類型,而不是指針類型,是以Funcp2前面還需要加上*
bool lengthCompare(const string&, const string&);


//Func和Func2都是函數類型


typedef bool Func(const string&, const string&);


typedef decltype(lengthCompare) Func2;


//FuncP和FuncP2都是函數指針類型


typedef bool(*FuncP)(const string&, const string&);


typedef decltype(lengthCompare) *FuncP2;


void useBigger(const string&, const string&, Func);


void useBigger2(const string&, const string&, FuncP);


int main()
{


bool (*pf)(const string&, const string&);


pf = lengthCompare;


  


useBigger("hello", "goodbye",lengthCompare);


useBigger("hello", "goodbye", pf);


useBigger2("hello", "goodbye", lengthCompare);


useBigger2("hello", "goodbye", pf);


return 0;


}      

八、傳回函數的指針

  • 函數和數組一樣不能直接通過傳回值傳回,而需要通過指針傳回

格式一:

  • 下面是原始的定義方法,比較繁瑣
  • 意義為:f1函數的參數為int,傳回值為函數指針類型,該函數指針指向的函數傳回值為int,參數為int*和int
int (*f1(int))(int*, int);

格式二:

  • 通過using聲明簡化
  1. using F = int(int*, int); //F為函數類型
  2. using PF = int(*)(int*, int);//PF為函數指針類型
  3. PF f1(int); //f1函數傳回一個函數指針,該指針指向的函數傳回值為int,參數為int*和int
  4. F* f1(int); //同上
  5. F f1(int); //錯誤,F為函數類型,不能直接傳回

格式三:

  • 通過C++11标準的尾置傳回類型的方式定義
auto f1(int)->int(*)(int*, int);

九、将auto和decltype用于函數與函數指針類型

  • 将我們知道一個函數的傳回值為某種函數指針類型時,可以使用decltype簡化書寫

示範案例

  • 例如下面的getFcn函數傳回值為sumLength函數指針類型,則可以使用下面的方法
  • 注意:decltype傳回的是函數類型,是以還需要加上指針
  1. string::size_type sumLength(const string&, const string&);
  2. string::size_type largerLength(const string&, const string&);
  3. decltype(sumLength) *getFcn();