C++ primer第六章6.7函數指針

函數指針

  • 函數指針指向的是函數而不是對象。和其他指針一樣,函數指針指向某種特定的類型。函數的類型由他的返回類型和形參類型共同決定,而與函數的名字無關。
//比較兩個string對象的長度
bool lengthCompare(const string &,const string &);
  • 要想聲明一個可以指向該函數的指針,只需要指針替換函數的名字即可
  • pf的名字之前有一個* ,因此pf是指針;右側是形參的列表,表示pf指向的是函數;觀察左側,發現函數的返回數值是bool類型的。因此,pf就是一個指向函數的指針,其中該函數的參數是兩個const string的引用,返回的是bool類型。
//pf指向一個函數,該函數的參數是兩個const string的引用,返回的數值是bool類型
bool (*pf)(const string &,const string &);//未初始化
  • *pf兩端的括號不可以省略,如果沒有這對括號,則pf是一個返回數值為bool的指針的函數
//聲明一個名為pf的函數,該函數返回bool *
bool *pf(const string &,const string &);//未初始化

使用函數指針

  • 當把函數的名字作為一個數值進行使用的時候,該函數會自動地轉化成指針。
//例如,按照如下的形式將lengthCompare的地址賦值給pf
//pf = lengthCompare; //pf指向名字為lengthCompare的函數
//pf = &lengthCompare;//等價的賦值語句,取地址符的符號是可選的
  • 還可以直接使用指向函數的指針調用該函數,而不需要提前解引用指針
bool b1 = pf("hello","goodbye"); //調用lengthCompare函數
bool b2 = (*pf)("hello","goodbye");//一個等價的調用
bool b3 = lengthCompare("hello","goodbye");//一個等價的調用
  • 指向不同函數類型的指針之間不存在轉換的規則,但是我們可以為函數指針賦值一個nullptr或者數值為0的整型常量的表達式,表示這個指針沒有指向任何一個函數

重載函數的指針

  • 當使用重載函數的時候,上下文必須界定該選用哪個函數。如果定義了指向重載函數的指針
void ff(int *);
void ff(unsigned int);
void (*pf1)(unsigned int) = ff;//pf1指向了ff(unsigned int)

函數的指針形參

  • 和數組類似,雖然不可以定義函數類型的形參,但是形參可以是指向函數的指針。此時形參看起來是函數的類型,實際上卻是當成指針來使用

?

//第三個形參是函數類型,他會自動的轉換成指針
void useBigger(const string &s1,const string &s2,bool pf(const string &,const string &));
//等價的聲明:顯式地將形參定義成指向函數的指針
void useBigger(const string &s1,const string &s2,bool (*pf)(const string &,const string &));
//可以把函數作為實參的使用,此時他會自動的轉化成指針
useBigger(s1,s2,lengthCompare)
  • 可以使用類型的別名和decltype來簡化使用函數指針的代碼
//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;  //等價的類型
  • decltype返回函數的類型,不會將函數的類型自動轉化成為指針類型。因為,decltype的類型是函數類型,因此只有在前面加上*,才可以得到指針。
//usingBigger的等價聲明,其中使用了類型的別名
void useBigger(const string &s1,const string &s2,Func);
void useBigger(const string &s1,const string &s2,Func);
  • 這兩個語句聲明的是同一個函數,在第一句中,編譯器自動的將Func表示的函數類型轉化為指針

返回指向函數的指針

  • 和數組類似,不能返回一個函數,但是可以返回一個指向函數的類型的指針。
  • 必須將返回的類型寫成指針的形式,編譯器不會自動的將函數的返回類型當成對應的指針類型進行處理。
  • 要想聲明一個返回函數指針的函數,最簡單的方法是使用類型別名
    using F = int(int*,int); //F是函數類型,不是指針using PF = int(*)(int *,int);//PF是指針類型
  • 和函數的形參一樣,返回的類型不會自動地轉化成指針。必須顯示將返回類型指定為指針。
PF f1(int); //正確,PF是指向函數的指針,f1返回指向函數的指針
F f1(int);  //錯誤,F是函數的類型,f1不可以返回一個函數
F *f1(int); //正確,顯示的指定返回的類型是指向函數的指針
  • 也可以直接使用下面的形式直接聲明f1? ?int(*f1(int))(int *,int);
  • 按照由內達外的形式閱讀這條語句,f1有形參列表,所以f1是一個函數;f1前面有*,所以f1返回的是一個指針,指針的類型本身也包含了形參的列表,因此指針指向函數,該函數的返回類型是int。
  • 還可以使用尾置返回的類型的方式來聲明一個返回函數指針的函數 auto f1(int) -> int (*)(int *,int);

將auto和decltype用于函數指針類型

  • 如果明確知道返回的函數是哪一個,就可以使用decltype簡化書寫函數指針返回類型的過程。
  • 假定有兩個函數,返回的類型都是string::size_type,并且各有兩個const string&類型的形參,編寫第三個函數,接收一個string類型的參數,返回一個指針,這個指針指向前兩個函數中的一個。
    string::size_type sumLength(const string &,const string &);string::size_type largerLength(const string &,const string &);//根據形參的取值,編寫的getFcn函數返回指向上面函數的其中一個decltype(sumLength) * getFcn(const string &);
  • 聲明getFcn唯一需要注意的地方是,牢記將decltype函數作用于某一個函數的時候,返回的是函數的類型而不是指針類型。因此,只有顯示地加上 * 表示需要返回的是指針,而不是函數的本身。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/447030.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/447030.shtml
英文地址,請注明出處:http://en.pswp.cn/news/447030.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android設計模式之——工廠方法模式

一、介紹 工廠方法模式(Factory Pattern),是創建型設計模式之一。工廠方法模式是一種結構簡單的模式,其在我們平時開發中應用很廣泛,也許你并不知道,但是你已經使用了無數次該模式了,如Android…

C++ primer第十八章 18.1小結 異常處理

18.1 異常處理 異常處理機制,允許程序獨立開發的部分能夠在運行的時候出現的問題進行通信并且做出相應的處理,異常的處理使得我們可以將問題的檢測和處理分離開來。程序的一部分負責檢測問題的出現,然后將解決這個問題的任務傳遞給程序的另一…

淺談equals與==

一、前言 示例代碼: public static void main(String[] args) throws IOException {String str1 new String("hello");String str2 new String("hello");String str3 "cde";String str4 "cde";int i1 3;int i2 3;In…

針對C++異常的學習

源碼 頭文件 sdf_exception.h #pragma once#include <exception> #include <string>namespace sdf {namespace common{using sdf_error_code_t uint32_t;class SdfException : std::exception{public:explicit SdfException(sdf_error_code_t errorCode) : erro…

Android設計模式之——抽象工廠模式

一、介紹 抽象工廠模式&#xff08;Abstract Factory Pattern&#xff09;&#xff0c;也是創建型設計模式之一。前一節我們已經了解了工廠方法模式&#xff0c;那么這個抽象工廠又是怎么一回事呢&#xff1f;大家聯想一下現實生活中的工廠肯定都是具體的&#xff0c;也就是說…

Android設計模式之——策略模式

一、介紹 在軟件開發中也常常遇到這樣的情況&#xff1a;實現某一個功能可以有多種算法或者策略&#xff0c;我們根據實際情況選擇不同的算法或者策略來完成該功能。例如&#xff0c;排序算法&#xff0c;可以使用插入排序、歸并排序、冒泡排序等。 針對這種情況&#xff0c;…

密碼學在區塊鏈隱私保護中的應用學習

身份隱私保護技術 混淆服務 混淆服務的目的在于混淆消息雙方的聯系&#xff08;如 圖 2 所示&#xff09;。當發送方需要告知接收方消息 M 時&#xff0c; 它會首先用接收方的公鑰 KB 加密 M&#xff0c;并在密文后 附帶真實接收地址 R。為了借助第三方&#xff08;圖 2 中的…

值類型和引用類型的區別

一、定義 引用類型表示你操作的數據是同一個&#xff0c;也就是說當你傳一個參數給另一個方法時&#xff0c;你在另一個方法中改變這個變量的值&#xff0c;那么調用這個方法是傳入的變量的值也將改變。 值類型表示復制一個當前變量傳給方法&#xff0c;當你在這個方法中改變…

面向區塊鏈的高效物化視圖維護和可信查詢論文學習

物化視圖介紹 如何維護物化視圖仍舊是一個開放問題.在關系數據庫中,增量刷新的物化視圖維護策略可劃分為立即維護和延遲維護兩大類.立即維護策略的優點是實現較為簡單,在單數據源下不 存在一致性問題;然而該策略將物化視圖維護過程嵌入到更新事務之中,延長了更新事務的提交時間…

Java基礎知識(一)

一、接口 類描述了一個實體&#xff0c;包括實體的狀態&#xff0c;也包括實體可能發出的動作。 接口定義了一個實體可能發出的動作。但是只是定義了這些動作的原型&#xff0c;沒有實現&#xff0c;也沒有任何狀態信息。 所以接口有點象一個規范、一個協議&#xff0c;是一個…

密碼學數字信封的介紹

對稱密碼和非對稱密碼 對稱密碼&#xff1a;加解密運算非常快&#xff0c;適合處理大批量數據&#xff0c;但其密碼的分發與管理比較復雜非對稱密碼&#xff1a;公鑰和私鑰分離&#xff0c;非常適合密鑰的分發和管理 數字信封的定義 如果將對稱密碼算法和非對稱密碼算法的優點…

Android設計模式之——狀態模式

一、介紹 狀態模式中的行為是由狀態來決定的&#xff0c;不同的狀態下有不同的行為。狀態模式和策略模式的結構幾乎完全一樣&#xff0c;但它們的目的、本質卻完全不一樣。狀態模式的行為是平行的、不可替換的&#xff0c;策略模式的行為是彼此獨立、可相互替換的。用一句話來…

Android設計模式之——責任鏈模式

一、介紹 責任鏈模式&#xff08;Iterator Pattern&#xff09;&#xff0c;是行為型設計模式之一。什么是”鏈“&#xff1f;我們將多個節點首尾相連所構成的模型稱為鏈&#xff0c;比如生活中常見的鎖鏈&#xff0c;就是由一個個圓角長方形的鐵環串起來的結構。對于鏈式結構…

目前基于區塊鏈的檔案防篡改系統的設計如何實現防篡改

架構設計圖 分析 為了保障檔案數據的安全性和隱私性&#xff0c;存儲檔案附件和檔案屬性存儲加密存儲在私有IPFS集群&#xff0c;檔案的IPFS地址和數字指紋存儲在私有區塊鏈上。公有區塊鏈定期存儲和檢查私有區塊鏈最新不可逆區塊的高度和哈希值&#xff0c;以保障私有區塊鏈上…

IPFS的文件存儲模式

IPFS是如何進行文件存儲的 IPFS采用的索引結構是DHT&#xff08;分布式哈希表&#xff09;&#xff0c;數據結構是MerkleDAG&#xff08;Merkle有向無環圖&#xff09; DHT(分布式哈希表) 參考鏈接MerkleDAG&#xff08;Merkle有向無環圖&#xff09; 參考鏈接MerkleDAG功能…

Android設計模式之——解釋器模式

一、介紹 解釋器模式&#xff08;Interpreter Pattern&#xff09;是一種用的比較少的行為型模式&#xff0c;其提供了一種解釋語言的語法或表達式的方式&#xff0c;該模式定義了一個表達式接口&#xff0c;通過該接口解釋一個特定的上下文。在這么多的設計模式中&#xff0c…

在Docker里面安裝Ubuntu,并且使用ssh進行連接

創建Ubuntu鏡像 1&#xff0c;拉取Ubuntu系統的鏡像 docker pull ubuntu2、查看拉取是否成功 docker images3&#xff0c;運行容器 docker run --name 新建的容器的名字 -ti -v /AAA:/BBB -d -p 3316:22 ubuntu(這個是鏡像的名字)宿主機根目錄中的AAA文件夾就映射到了容器…

Android設計模式之——命令模式

一、介紹 命令模式&#xff08;Command Pattern&#xff09;&#xff0c;是行為型設計模式之一。命令模式相對于其他的設計模式來說并沒有那么多的條條框框&#xff0c;其實它不是一個很”規范“的模式&#xff0c;不過&#xff0c;就是基于這一點&#xff0c;命令模式相對于其…

C++ 序列化和反序列化學習

定義 程序員在編寫應用程序的時候往往需要將程序的某些數據存儲在內存中&#xff0c;然后將其寫入某個文件或是將它傳輸到網絡中的另一臺計算機上以實現通訊。這些過程將會涉及到程序數據轉化成能被存儲并傳輸的格式&#xff0c;因此被稱為“序列化”&#xff08;Serializatio…

Android設計模式之——觀察者模式

一、介紹 觀察者模式是一個使用率非常高的模式&#xff0c;它最常用的地方是GUI系統、訂閱——發布系統。因為這個模式的一個重要作用就是解耦&#xff0c;將被觀察者和觀察者解耦&#xff0c;使得它們之間的依賴性更小&#xff0c;甚至做到毫無依賴。以GUI系統來說&#xff0…