【c++】23.【函数指针】定义? 为什么不直接调用函数而要使用函数指针?
1. 函數指針及其定義和用法,C語言函數指針詳解
原文鏈接:http://c.biancheng.net/view/228.html
什么是函數指針
如果在程序中定義了一個函數,那么在編譯時系統就會為這個函數代碼分配一段存儲空間, 這段存儲空間的首地址稱為這個函數的地址。而且函數名表示的就是這個地址。既然是地址我們就可以定義一個指針變量來存放,這個指針變量就叫作 函數指針變量,簡稱 函數指針。那么這個指針變量怎么定義呢?
雖然同樣是指向一個地址,但指向函數的指針變量同我們之前講的指向變量的指針變量的定義方式是不同的。例如:
int(*p)(int, int);這個語句就定義了一個指向函數的指針變量p。
- 首先,它是一個指針變量,所以要有一個*,即(*p);
- 其次,前面的int 表示這個指針變量可以指向返回值類型為 int 型的函數;后面括號中的兩個 int 表示這個指針變量可以指向有兩個參數且都是 int 型的函數。
- 所以合起來這個語句的意思就是:定義了一個指針變量p,p可以指向返回值類型為int型,且有兩個int型參數的函數。p 的類型為int(*)(int,int)。
所以函數指針的定義方式為:
函數返回值類型表示該指針變量可以指向具有什么返回值類型的函數;
函數參數列表表示該指針變量可以指向具有什么參數列表的函數。這個參數列表中只需要寫函數的參數類型即可。
我們看到,函數指針的定義就是將函數聲明中的函數名改成(*指針變量名)。
但是這里需要注意的是:(*指針變量名)兩端的括號()不能省略,括號改變了運算符的優先級。如果省略了括號,就不是定義函數指針而是一個函數聲明了,即聲明了一個返回值類型為指針型的函數。
那么怎么判斷一個指針變量是指向變量的指針變量還是指向函數的指針變量呢?
- 首先看變量名前面有沒有*,如果有*說明是指針變量;
- 其次看變量名的后面有沒有帶有形參類型的圓括號(),如果有就是指向函數的指針變量,即函數指針,如果沒有就是指向變量的指針變量。
最后需要注意的是,指向函數的指針變量沒有++ 和--運算。
如何用函數指針調用函數
給大家舉一個例子:int Func(int x); /*聲明一個函數*/ int (*p) (int x); /*定義一個函數指針*/ p = Func; /*將Func函數的首地址賦給指針變量p*/
賦值時函數 Func 不帶括號,也不帶參數。由于函數名 Func 代表函數的首地址,因此經過賦值以后,指針變量 p 就指向函數 Func() 代碼的首地址了。
下面來寫一個程序,看了這個程序你們就明白函數指針怎么使用了:
輸出結果是:
2. 知乎問題:C++中函數指針有什么作用? 為什么不直接調用函數而要使用函數指針?
原文鏈接:https://www.zhihu.com/question/349498301
貓之公爵公之貓12 人贊同了該回答我覺得這個問題。。。可以去好好看看B站上有個講設計模式的視頻,講的非常好。。。。
簡單來講,函數指針,和虛函數有著一樣的用處(其實他們本質上也是一樣的),都是為了一個作用:延時綁定(晚綁定)。
這也是一個語言中,框架和庫的區別。。。
以前的C程序想用別人的東西,大部分都是庫,是一堆代碼的集合,所以你要用庫,就是調用它的功能,然后返回。。??蚣艿某霈F改變了這種情況,比如MFC框架(或者windows sdk),它要修改一個窗口的顏色,但是框架并不知道你的窗口是什么類型,它只關心它要修改的數據。。。這個時候就需要函數指針的幫助了。(注意,這個重點就在于,框架是不知道類型的,因為它寫框架代碼的時候,你還沒有寫窗口代碼),我給一個例子,這個例子多少有點不合適,因為C++通用做法肯定是虛函數了。。。但是這個方法本質上就是用函數指針模擬虛函數,只不過虛函數機制是編譯器生成的。
框架代碼:
#include <iostream>// 框架代碼 typedef void(ChangeColorFun)(Window* pWindow, int color);struct Window {ChangeColorFun* ChangeFun; };struct FrameWord {void SetWindow(Window* pWindow) {m_pWindow = pWindow;}void Run() {m_pWindow->ChangeFun(m_pWindow, 1000);}Window* m_pWindow = nullptr; };用戶代碼:
// 用戶代碼struct LinuxWindow : public Window {int m_LinuxColor = 0; };struct MacWindow : public Window {int m_MacColor = 0; };void ChangeLinuxColor(Window* pWindow, int color) {LinuxWindow* pLinuxWindow = (LinuxWindow*)pWindow;pLinuxWindow->m_LinuxColor = color; }void ChangeMaxColor(Window* pWindow, int color) {MacWindow* pLinuxWindow = (MacWindow*)pWindow;pLinuxWindow->m_MacColor = color; }int main() {FrameWord Frame; // 框架代碼Window* pWindow = new LinuxWindow; // 用戶代碼pWindow->ChangeFun = ChangeLinuxColor; // 用戶代碼Frame.SetWindow(pWindow); // 框架代碼Frame.Run(); // 框架代碼 delete pWindow; }注意看,框架代碼是寫框架的人之前就確定的,特別是在這個函數
void Run(){m_pWindow->ChangeFun(m_pWindow, 1000); }中,框架是完全不知道它拿到的是什么東西的,但是通過函數指針,框架并不需要確定這個對象是什么,這樣就做到了晚綁定機制,函數指針在這里就是提供了一個接口,這個接口規定了框架作者要做什么,用戶代碼要做什么。
現代C++框架機制錯綜復雜,大部分人寫代碼的時候是既要寫服務代碼,又要寫用戶代碼,這個時候區分出來他們的區別是非常重要的,按照用戶代碼的思路寫框架代碼,你的代碼會很難復用;反之按照框架代碼的思路去寫用戶代碼,你的代碼實現會過因為過于靈活復雜難用且功能可能很多用不到。
題主估計寫框架代碼少,所以才問這個問題的
補上b的設計模式的鏈接。。。
https://b23.tv/wrqjt5
總結
以上是生活随笔為你收集整理的【c++】23.【函数指针】定义? 为什么不直接调用函数而要使用函数指针?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【c++】25.事件驱动的详解
- 下一篇: 【c++】24.std::functio