无锡教育网:C++ 函数重载,函数模板和函数模板重载,选择哪一个?

admin 2个月前 (05-05) 科技 4 0

重载剖析

  在C++中,对于函数重载、函数模板和函数模板重载,C++需要有一个优越的计谋,去选择挪用哪一个函数界说(尤其是多个参数时),这个历程称为重载剖析

  (这个历程将会非常复杂,希望不要遇到一定要写这种代码的时刻。)

 

大致步骤

  Ⅰ.建立候选函数列表(其中包罗与候选函数相同名称的函数和模板函数)。

  Ⅱ.使用候选函数列表建立可行函数列表(要求参数数目准确,为此有一个隐式类型转换序列,其中包罗实参类型与响应的形参类型完全匹配的情形。例如,使用float参数的函数挪用可以将该参数转换为double类型,从而与double匹配,而模板函数可以为float类型天生一个函数实例)。

  Ⅲ.确定是否有最佳的可行函数(若是有则挪用,没有则报错)。

 

  我们以只有一个参数的函数为例:

 1 may('B');    // 函数挪用
 2 
 3 /*以下是一系列候选函数声明*/
 4 void may(int);                          // #1
 5 float may(float, float = 3);        // #2
 6 void may(char);                        // #3
 7 char * may(coNSt char *);            // #4
 8 char may(const char &);              // #5
 9 template<class T> void may(const T &);    // #6
10 template<class T> void may(T *);          // #7

  这些函数声明都市进入函数列表(由于名称相同),接下来思量特征标(参数数目与类型),不思量返回值。其中#4和#7不可行,由于整数无法隐式类型转换为指针类型。#6可用来天生详细化,其中T被替换为char类型,此时还剩下5个可行的函数(#1、#2、#3、#5、#6)。若是此时只剩下一个,那么任何一个都可以准确使用

  

  接下来,到了择优环节。这一步主要考量的是函数挪用参数与可行的候选函数的参数匹配所需要举行的转换。通常,从最佳到最差的顺序如下:

   1、完全匹配,函数优于模板。

   2、提升转换(例如,char和short自动转换为int,float自动转换为double)。

   3、尺度转换(例如,int转换为char,long转换为double)。

   4、用户界说的转换,如类声明中界说的转换。

  在剩余的5个函数中,#1优于#2,由于char到int是提升转换,而char到float是尺度转换(此时还剩#1,#3,#5,#6)。#3、#5、#6优于#1和#2,由于他们是完全匹配(还剩#3,#5,#6)。#3和#5优于#6,由于#6是模板(还剩#3和#5)。

  这时,会泛起两个问题,完全匹配到底是什么?若是有两个完全匹配(#3和#5)该怎么办?通常有两个完全匹配是一种错误,但这一规则有两个破例。

 

完全匹配和最佳匹配

  举行完全匹配时,C++允许某些“无关紧要的转换”,下表列出了这些转换——Type示意随便类型。例如,int到int &,注重,Type可以是char &这样的类型,因此,这些规则也包罗char &到const char &的转换。

完全匹配允许的无关紧要的转换
从实参 到形参
Type Type &
Type &  Type
Type[] * Type
Type(参数列表) Type(*)(参数列表)
Type const Type
Type volatile Type
Type * const Type
Type * volatile Type *

   假设有如下代码:

1 struct blot {int a; char b[10]};
2 blot ink = {25, "spots"};
3 recycle(ink);
4 
5 // 下面的原型完全匹配
6 void recycle(blot);          // #1 blot to blot
7 void recycle(const blot);   // #2 blot to const blot
8 void recycle(blot &);     // #3 blot to blot &
9 void recycle(const blot &); // #4 blot to const blot &

   若是有多个完全匹配的原型,则无法完成重载剖析历程,若是没有最最佳的可行函数,编译器将报错。

  然而,有这样的破例规则,首先,指向非const数据的指针和引用优先于非const指针和引用,在上例中,若是只界说了#3和#4,将选择#3,由于ink没有被声明为const,然而const和非const之间的区别只适用于指针和引用指向的数据,也就是说,若是只界说了#1和#2,将泛起二义性错误。

  一个完全匹配优于另一个的另一种情形是,其中一个是非模板函数而另一个不是,这种情形下,非模板函数将优先于模板函数(包罗显式详细化)。

  若是两个完全匹配的函数都是模板函数,则较详细的模板函数优先,这意味着显示详细化将优于模板隐式天生的详细化。

1 struct blot {int a; char b[10]};
2 template <class Type> void recycle(Type t);  // 模板
3 template <> void recycle<blot>(blot & t);    // 显示详细化
4 
5 blot ink = {25, "spots"};
6 recycle(ink);    //使用显示详细化

  术语“最详细”并不一定意味着显示详细化,而是指编译器推断使用哪种类型时执行的转换最少。例如:

1 struct blot {int a; char b[10]};
2 template <class Type> void recycle(Type t);    // #1
3 template <class Type> void recycle(Type * t);  // #2
4 
5 blot ink = {25, "spots"};
6 recycle(&ink);    // 使用#2,由于转换最少,#2被认为是更详细的

  用于找出最详细的模板的规则被称为部门排序规则

 

部门排序规则

 1 template <typename T>
 2 void show(T arr[], int n);     // #1
 3 
 4 template <typename T>
 5 void show(T * arr[], int n);   // #2
 6 
 7 struct debts
 8 {
 9     char name[50];
10     double amount;
11 };
12 
13 ......
14 
15 int things[6] = {13,31,103,301,310,130};
16 debts mr[3] = 
17 {
18    {"aaa", 24.1},
19    {"bbb", 25.2},
20    {"ccc", 26.3}   
21 };
22 double * pd[3];
23 
24 for(int i=0; i<3; i++)
25 {
26    pd[i] = &mr[i].amount;          
27 }
28 
29 show(things, 6); // 使用#1
30 show(pd, 3);    // 使用#2

   things是一个int数组,与#1匹配,其中T被替换为int。pd是一个double *数组,与#1匹配时,T被替换为double *,与#2匹配时,T被替换为double。在这两个模板中,#2加倍详细,由于它做了特定的假设,数组内容是指针,因此被使用。若是将#2从程序中删除,那么使用#1,将显示出地址,而不是值。

  总之,重载剖析将寻找最匹配的函数,若是只存在一个这样的函数,则选择它;若是存在多个这样的函数,但其中只有一个非模板函数,则选择它;入伏哦存在多个合适的函数且都为模板函数,但其中只有一个函数比其他函数更详细,则选择它。其他情形(有多个非模板或模板函数,但没有一个比其他更详细,或基本不存在匹配的函数)均为错误。

 

建立自界说选择

  在有些情形下,可以指导编译器做出你希望的选择。

 1 template<class T>
 2 T lesser(T a, T b);           // #1
 3 
 4 int lesser(int a, int b);     // #2
 5 
 6 ......
 7 
 8 int m = 20;
 9 int n = -30;
10 double x = 15.5;
11 double y = 25.9;
12 
13 lesser(m, n);                // 使用#2
14 lesser(x, y);                // 使用#1,T被转换为double类型
15 lesser<>(m, n);              // <>提醒编译器,使用模板函数,使用#1
16 lesser<int>(x, y);           // 显式实例化,将使用实例化后的函数x,y被强制转换为int类型

 

多个参数的函数

  将有多个参数的函数挪用与有多个参数的原型举行匹配时,情形将非常复杂。编译器必须思量所有参数的匹配情形。若是找到比其他可行函数都合适的函数,则选择该函数。一个函数要比其他函数都合适,其所有参数的匹配水平都必须不必其他函数差,同时至少有一个参数的匹配水平比其他函数高。

,

Sunbet

www.0379st.com信誉来自于每一位客户的口碑,Sunbet贴心的服务,让你尊享贵宾通道,秒速提现,秒速到账,同行业中体验最佳。

AllBetGaming声明:该文看法仅代表作者自己,与本平台无关。转载请注明:无锡教育网:C++ 函数重载,函数模板和函数模板重载,选择哪一个?

网友评论

  • (*)

最新评论

站点信息

  • 文章总数:594
  • 页面总数:0
  • 分类总数:8
  • 标签总数:928
  • 评论总数:180
  • 浏览总数:4659