亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

深入了解C++函數(shù)重載解析策略

 更新時間:2022年10月20日 08:18:52   作者:木三百川  
這篇文章主要為大家詳細介紹了C++中函數(shù)重載的解析策略,文中的示例代碼講解詳細,對我們學習C++有一定幫助,感興趣的小伙伴可以了解一下

參考《C++ Primer Plus》(第6版)中文版,Stephen Prata 著,張海龍 袁國忠譯,人民郵電出版社。C++ 使用重載解析策略來決定為函數(shù)調(diào)用使用哪一個函數(shù)定義。重載解析過程大致分為如下三步:

第 1 步:創(chuàng)建候選函數(shù)列表,只要求函數(shù)名一樣即可,對函數(shù)特征標以及是否為模板函數(shù)無要求;

第 2 步:在上一步的基礎(chǔ)上創(chuàng)建可行函數(shù)列表,包含特征標完全匹配的常規(guī)函數(shù)或模板函數(shù)、以及實參隱式轉(zhuǎn)換后完全匹配的常規(guī)函數(shù)或模板函數(shù),這些都是參數(shù)數(shù)目正確的函數(shù);

第 3 步:在上一步的基礎(chǔ)上確定最佳匹配函數(shù),若有則使用它,若沒有則該函數(shù)調(diào)用失敗。

下面以一個例子來說明這個重載過程:

//全部函數(shù)原型
void may(int);                        //原型#1
float may(float, float = 3);          //原型#2
void may(char);                       //原型#3
char * may(const char *);             //原型#4
char may(const char &);               //原型#5
template<class T> void may(const T &);//原型#6
template<class T> void may(T *);      //原型#7
void may(char, double);               //原型#8
void mbk(float);                      //原型#9
char mkk(int, char);                  //原型#10
int mck(char);                        //原型#11
double myk(float);                    //原型#12
void mpk(char);                       //原型#13
 
//函數(shù)調(diào)用
may('B');
 
//函數(shù)定義
...

重載第 1 步:創(chuàng)建候選函數(shù)列表。即函數(shù)名稱為 may 的常規(guī)函數(shù)和模板函數(shù),候選函數(shù)列表如下:

//重載第1步:創(chuàng)建候選函數(shù)列表
void may(int);                        //原型#1
float may(float, float = 3);          //原型#2
void may(char);                       //原型#3
char * may(const char *);             //原型#4
char may(const char &);               //原型#5
template<class T> void may(const T &);//原型#6
template<class T> void may(T *);      //原型#7
void may(char, double);               //原型#8

重載第 2 步:創(chuàng)建可行函數(shù)列表。由于整數(shù)類型 char 不能被隱式地轉(zhuǎn)換為指針類型 char *,因此函數(shù) #4 和函數(shù) #7 都被排除,而函數(shù) #8 因為參數(shù)數(shù)目不匹配也會被排除。進行完全匹配時,C++ 允許下表這些無關(guān)緊要的轉(zhuǎn)換,表中 Type 表示任意類型,例如 char & 到 const char & 的轉(zhuǎn)換也包含在內(nèi),表中 Type (argument-list) 意味著用作實參的函數(shù)名和用作形參的函數(shù)指針只要返回類型和參數(shù)列表相同,就是匹配的。

實參類型形參類型
TypeType &
Type &Type
Type []Type *
Type (argument-list)Type (*) (argument-list)
Typeconst Type
Typevolatile Type
Type *const Type *
Type *volatile Type *

根據(jù)此表可知,剩下的函數(shù)中包含特征標完全匹配的常規(guī)函數(shù) #3 和 #5、特征標完全匹配的模板函數(shù) #6(此時 T 可以被實例化為 char)、實參隱式轉(zhuǎn)換后完全匹配的常規(guī)函數(shù) #1 和 #2。可行函數(shù)列表如下:

//重載第2步:創(chuàng)建可行函數(shù)列表
void may(int);                        //原型#1
float may(float, float = 3);          //原型#2
void may(char);                       //原型#3
char may(const char &);               //原型#5
template<class T> void may(const T &);//原型#6

重載第 3 步:確定最佳匹配函數(shù)。通常,從最佳到最差的順序如下所述:

  • 特征標完全匹配;
  • 類型需經(jīng)隱式提升轉(zhuǎn)換,例如 char 和 short 自動轉(zhuǎn)換為 int,float 自動轉(zhuǎn)換為 double;
  • 類型需經(jīng)隱式標準轉(zhuǎn)換,例如 int 轉(zhuǎn)換為 char,long 轉(zhuǎn)換為 double;
  • 類型需經(jīng)隱式自定義轉(zhuǎn)換,例如類中用戶定義的類型轉(zhuǎn)換。

依此規(guī)則,函數(shù) #3 和函數(shù) #5、函數(shù) #6 都是特征標完全匹配的最佳匹配函數(shù),函數(shù) #1 需經(jīng)隱式提升轉(zhuǎn)換,函數(shù) #2 需經(jīng)隱式標準轉(zhuǎn)換,由此各函數(shù)最佳匹配程度為:(#3, #5, #6) > #1 > #2。當特征標完全匹配時,又有如下規(guī)則:

  • 指向非 const 數(shù)據(jù)的指針和引用優(yōu)先與形參為非 const 指針和引用的函數(shù)匹配;
  • 優(yōu)先與非模板函數(shù)匹配;
  • 同為模板函數(shù)時,優(yōu)先與較具體的模板函數(shù)匹配。

依此規(guī)則,非模板函數(shù) #3 和 #5 最佳匹配程度要高于模板函數(shù) #6 ,即各函數(shù)最佳匹配程度為:(#3, #5) > #6 > #1 > #2。最終出現(xiàn)了兩個最佳匹配函數(shù) #3 和 #5 ,因此該函數(shù)調(diào)用失敗,編譯器將報錯。

//重載第 3 步:確定最佳匹配函數(shù)
void may(char);                       //原型#3
char may(const char &);               //原型#5

下面展開來說上述幾條完全匹配時的規(guī)則。

第 1 條:指向非 const 數(shù)據(jù)的指針和引用優(yōu)先與形參為非 const 指針和引用的函數(shù)匹配,這一點需明確,const 和非 const 之間的區(qū)別只適用于指針和引用。下面 4 個函數(shù)都與函數(shù)調(diào)用是完全匹配的:

//函數(shù)原型
void recycle(int);        //原型#1
void recycle(const int);  //原型#2
void recycle(int &);      //原型#3
void recycle(const int &);//原型#4
 
//函數(shù)調(diào)用
int x = 5;
recycle(x);
 
//函數(shù)定義
...
  • 如果這 4 個函數(shù)同時存在,則無法完成重載,編譯器會報多義性匹配的錯誤;
  • 如果只存在函數(shù) #1 與 #2,則無法完成重載,編譯器會報重復(fù)定義的錯誤;
  • 如果只存在函數(shù) #1 與 #3,則無法完成重載,編譯器會報多義性匹配的錯誤;
  • 如果只存在函數(shù) #1 與 #4,則無法完成重載,編譯器會報多義性匹配的錯誤;
  • 如果只存在函數(shù) #2 與 #3,則無法完成重載,編譯器會報多義性匹配的錯誤;
  • 如果只存在函數(shù) #2 與 #4,則無法完成重載,編譯器會報多義性匹配的錯誤;
  • 如果只存在函數(shù) #3 與 #4,則函數(shù)調(diào)用時編譯器將會選擇 #3。

第 2 條:優(yōu)先與非模板函數(shù)匹配,這一點比較簡單,當完全匹配的函數(shù)中,一個是非模板函數(shù),另一個是模板函數(shù)時,非模板函數(shù)將優(yōu)于模板函數(shù),顯式具體化、顯式實例化、隱式實例化都屬于模板函數(shù)。

第 3 條:同為模板函數(shù)時,優(yōu)先與較具體的模板函數(shù)匹配,找出最具體的模板的規(guī)則被稱為函數(shù)模板的部分排序規(guī)則(partial ordering rules)。這意味著顯式具體化優(yōu)先于常規(guī)模板函數(shù),都為常規(guī)模板函數(shù)時,編譯器優(yōu)先選擇實例化時類型轉(zhuǎn)換更少的那一個。以下面的程序為例,調(diào)用方式 recycle(&ink) 既與模板 #1 匹配,此時 Type 將被解釋為 blot *,也與模板 #2 匹配,此時 Type 將被解釋為 blot,因此將這兩個隱式實例 recycle<blot *>(blot *) 和 recycle<blot>(blot *) 發(fā)送到可行函數(shù)池中。在選擇最佳匹配函數(shù)時,#2 被認為是更具體的,因為它已經(jīng)顯式地指出,函數(shù)參數(shù)是指向 Type 的指針,相比于 #1,它對類型的要求更加地具體,在生成過程中所需要的轉(zhuǎn)換更少,因此調(diào)用方式 recycle(&ink) 實際會匹配版本 #2。

//兩個常規(guī)模板函數(shù)
template <class Type> void recycle(Type t);   //原型#1
template <class Type> void recycle(Type * t); //原型#2
 
//調(diào)用程序包含如下代碼
struct blot {int a; char b[10];};
blot ink = {25, "spots"};
...
recycle(&ink);  //使用版本#2
 
//函數(shù)定義
...

部分排序規(guī)則的另一個示例程序如下,它與上一個例子有異曲同工之妙。由于模板 #2 做了特定的假設(shè):數(shù)組內(nèi)容是指針,對類型的要求更加地具體,因此在調(diào)用時第一個參數(shù)若傳入指針數(shù)組 pt,則將實際匹配函數(shù) #2。

//兩個常規(guī)模板函數(shù)
template <typename T> 
void ShowArray(T arr[], int n);   //原型#1
template <typename T> 
void ShowArray(T * arr[], int n); //原型#2
 
//調(diào)用程序包含如下代碼
int things[6] = {13, 31, 103, 301, 310, 130};
int * pt[3] = {&things[0], &things[2], &things[4]};
ShowArray(things, 6);  //使用版本#1
ShowArray(pt, 3);      //使用版本#2
 
//函數(shù)定義
...

將有多個參數(shù)的函數(shù)調(diào)用與有多個參數(shù)的原型進行匹配時,編譯器必須考慮所有參數(shù)的匹配情況。如果找到比其他可行函數(shù)都合適的函數(shù),則選擇該函數(shù)。一個函數(shù)要比其他函數(shù)都合適,其所有參數(shù)的匹配程度都必須不比其他函數(shù)差,同時至少有一個參數(shù)的匹配程度比其他函數(shù)都高。

在有些情況下,可通過編寫合適的函數(shù)調(diào)用,來引導(dǎo)編譯器做出程序員期望的選擇。如下所示,其中模板函數(shù)返回兩個值中較小的一個,非模板函數(shù)返回兩個值中絕對值較小的那個。第一次調(diào)用時根據(jù)重載解析策略選擇了非模板函數(shù) #2;第二次調(diào)用時根據(jù)重載解析策略選擇了模板函數(shù) #1 的 double 版本,屬于模板函數(shù)的隱式實例化;第三次調(diào)用的 <> 指出,編譯器應(yīng)該選擇模板函數(shù),此時編譯器會查看調(diào)用函數(shù)時的實參類型來進行實例化,也屬于模板函數(shù)的隱式實例化;第四次調(diào)用的 <int> 顯式指出,編譯器應(yīng)該使用模板函數(shù)的 int 實例化版本,此時屬于模板函數(shù)的顯式實例化。

#include <iostream>
 
//函數(shù)#1
template<class T>
T lesser(T a, T b)
{
    return a < b ? a : b;
}
 
//函數(shù)#2
int lesser(int a, int b)
{
    a = a < 0 ? -a : a;
    b = b < 0 ? -b : b;
    return a < b ? a : b;
}
 
//函數(shù)調(diào)用
int main()
{
    using namespace std;
    
    int m = 20;
    int n = -30;
    double x = 15.5;
    double y = 25.9;
    
    //使用#2,結(jié)果為20
    cout << lesser(m, n) << endl;
    
    //使用#1,double隱式實例化,結(jié)果為15.5
    cout << lesser(x, y) << endl;
    
    //使用#1,int隱式實例化,結(jié)果為-30
    cout << lesser<>(m, n) << endl;
    
    //使用#1,int顯式實例化,結(jié)果為15
    cout << lesser<int>(x, y) << endl;
    
    return 0;
}

到此這篇關(guān)于深入了解C++函數(shù)重載解析策略的文章就介紹到這了,更多相關(guān)C++函數(shù)重載解析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++學習小結(jié)之數(shù)據(jù)類型及轉(zhuǎn)換方式

    C++學習小結(jié)之數(shù)據(jù)類型及轉(zhuǎn)換方式

    本文給大家分享的是本人在學習C++過程中的一個小心得,關(guān)于數(shù)據(jù)類型和轉(zhuǎn)換方式的,這里記錄下來,推薦給菜鳥們,高手大神請直接飄過。
    2015-07-07
  • 在C++?中慎用setjmp和longjmp解析

    在C++?中慎用setjmp和longjmp解析

    setjmp和longjmp是C語言中用于實現(xiàn)非局部跳轉(zhuǎn)的函數(shù),setjmp和longjmp 是 C 語言中一個很強大的函數(shù),這篇文章主要介紹了在C++?中慎用setjmp和longjmp的相關(guān)知識,需要的朋友可以參考下
    2023-06-06
  • 一起來學習C語言的程序環(huán)境與預(yù)處理

    一起來學習C語言的程序環(huán)境與預(yù)處理

    這篇文章主要為大家詳細介紹了C語言程序環(huán)境與預(yù)處理,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • C/C++實現(xiàn)圖形學掃描線填充算法

    C/C++實現(xiàn)圖形學掃描線填充算法

    這篇文章主要介紹了C/C++實現(xiàn)圖形學掃描線填充算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • c++中inline的用法分析

    c++中inline的用法分析

    本篇文章是對c++中inline的用法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C++11返回類型后置語法的使用示例

    C++11返回類型后置語法的使用示例

    本篇文章主要介紹了C++11返回類型后置語法的使用示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • C指針原理教程之AT&T匯編

    C指針原理教程之AT&T匯編

    AT&T 匯編是一種和intel匯編在語法上完全不同的匯編語言,為避免混淆intel語法,本文只介紹AT&T匯編,AT&T的第一個特點就是每個寄存器名前必須加‘%’,立即數(shù)前必須加‘$’
    2019-02-02
  • vc控制臺程序關(guān)閉事件時的處理方式及注意點詳解

    vc控制臺程序關(guān)閉事件時的處理方式及注意點詳解

    在本篇文章里小編給大家整理的是一篇關(guān)于vc控制臺程序關(guān)閉事件時的正確處理方式的相關(guān)知識點內(nèi)容,對此有需求的朋友們可以參閱下。
    2021-12-12
  • C語言實現(xiàn)簡單的學生學籍管理系統(tǒng)

    C語言實現(xiàn)簡單的學生學籍管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡單的學生學籍管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • C語言 數(shù)據(jù)結(jié)構(gòu)鏈表的實例(十九種操作)

    C語言 數(shù)據(jù)結(jié)構(gòu)鏈表的實例(十九種操作)

    這篇文章主要介紹了C語言 數(shù)據(jù)結(jié)構(gòu)鏈表的實例(十九種操作)的相關(guān)資料,需要的朋友可以參考下
    2017-07-07

最新評論