Cpp primer<<学习函数-实参类型转换、指向函数的指针_3

本文详细介绍了C++中函数参数的类型转换,包括精确匹配、类型提升和转换,以及枚举类型在参数匹配中的作用。同时,阐述了如何使用指向函数的指针,包括函数指针的定义、初始化、赋值以及通过指针调用函数。此外,还讨论了函数指针作为函数参数和返回值的情况,以及如何指向重载函数。
摘要由CSDN通过智能技术生成

实参类型转换

转换优先等级以降序排列

  • 精确匹配
  • 通过类型提升实现的匹配
void f(int)
 int main()
 {
     f('a');  //ok:calls f(int)
     return 0;
 }
  • 通过标准转换实现的匹配
void f(int*)
 void f(int*,int*)
 int main()
 {
     int a[] = {1,3};
     f(a); //ok:calls f(int *)
     return 0;
 }
  • 通过类类型转换实现的匹配
    1. 需要类型提升或转换的匹配
void f(int);
void f(short);
int main()
{
    f('a');//ok:calls f(int);
    return 0;
}

需要类型转换的匹配”劣于”需要类型提升的匹配。

void f(long);
void f(float);
int main()
{
    f(3.14);// errror:ambigious call
    return 0;
}//各个标准转换之间具有相同的转换优先级

2.参数匹配与枚举类型
枚举(enum)类型对象只能用同一枚举类型的另一个对象或一个枚举成员进行初始化。

enum e1{a = 2,b = 3,c  = 4};
e1 ea = a;   // 利用枚举成员进行初始化
e1 ea1 = ea; // 用枚举类型的另一对象进行初始化

整数对象即使具有与枚举元素相同的值也不能用于调用期望获得枚举类型实参的函数。

enum Tokens{INLINE = 128,VIRTUAL = 129};
void ff(Tokens);
void ff(int)
int main()
{
    Tokens curTok = INLINE;
    ff(128);    //exactly matches ff(int)
    ff(INLINE); //exactly matches(Tokens)
    ff(curTok); //exactly matches(Tokens)
    return 0;
}

无法将整型值传递给枚举类型的形参,单可以将枚举值传递给整形形参。此时枚举值被提升为int型或更大的整形。具体提升类型取决于枚举成员的值。如果是重载函数,枚举值提升后的类型将决定出最佳匹配函数。

void newf(unsigned char);
void newf(int);
unsigned char uc= 129;
newf(VIRTUAL);  //calls newf(int)
newf(uc);       //calls newf(unsigned char)

由于不同枚举类型的枚举常量值不相同,在函数重载确定过程中,不同的枚举类型会具有完全不同的行为。其枚举成员决定了他们提升的类型,而所提升的类型依赖于机器。

3.重载或const形参
仅当形参是引用或指针时,形参是否为const才有影响。
可基于函数的引用形参是指向const对象还是指向非const对象,实现重载。

Record lookup(Account &);
Record lookup(const Account &);
int main()
{
    const Account a(0);
    Account b;
    lookup(a);  // matches Record lookup(const Account &)
    lookup(b); // matches Record lookup(Account &) 属于精确匹配
    return 0;
}

指向const类型的指针和指向非const类型的指针作为函数形参跟引用的法则一致。只是,不能基于指针本身是否为const:

void f(int *);
void f(int *const);  //Redeclaration (重复声明)

指向函数的指针

函数指针是指指向函数而非指向对象的指针。函数类型由其返回类型以及形参表确定,而与函数名无关。函数名表示函数地址。

// pf points to function returning bool that takes two const string references
bool (*pf)(const string &,const string &);
// declare a function named pf that returns a bool *
bool *pf(const string &,const string &);
  1. 用typedef简化函数指针的定义
    使用typedef为指针类型定义同义词,可将函数指针的使用大大简化:
typedef bool (*cmpFcn)(const string &, const string &);

该指针类型为”指向返回bool类型并带有两个const string 引用形参的函数的指针”。
2. 指向函数的指针的初始化和赋值
在引用函数名但又没有调用该函数时,函数名将被自动解释为指向函数的指针。

// compares lengths of two strings
bool lengthCompare(const string &,const string &);

除了用作函数调用的左操作数,否则对lengCompare函数的任何使用将解释为:

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

可使用函数名对函数指针做初始化或复制:

cmpFcn pf1 = 0;     // ok:unbount poiter to function
cmpFcn pr2 = lengthCompare  //pointer type matches function’s type
pf1 = lengthCompare;    //ok:pointer type matches function’s type
pf2 = pf1;              //ok:poiter types match

直接引用函数名等效于在函数名上应用取地址操作符:

cmpFcn pf1 = lengthCompare;
cmpFcn pf2 = &lengthCompare;

函数指针只能通过同类型的函数或函数指针或0值常量表达式进行初始化或赋值。用0值初始化函数指针,表示该指针不指向任何函数。
指向不同函数类型的指针之间不存在转换:

string::size_type sumLength(const string &,con string &);
bool cstringCompare(char *,char *);
// pointer to function returning bool taking two const string &
cmpFcn pf;
pf = sumLength;       //error:return type differs
pf = cstringCompare;  //error:parameter types differ
pf = lengthCompare;   //ok:function and pointer types match exactly

3.通过指针调用函数
指向函数的指针可用于调用它所指向的函数。

cmpFcn pf = lengthCompare;  //初始化
lengthCompare(“hi”,”bye”);   // direct call
pf(“hi”,”bye”); // equivalent call: pf1 implicitly dereferenced 
                //隐式引用
(*pf)(“hi”,”bye”); // equivalent call: pf1 explicitly deferenced 
                   //明确引用

如果指向函数的指针没有初始化,或者具有0值,则该指针不能在函数调用中使用。
4.函数指针形参
函数的形参可以是指向函数的指针。

void useBigger(const string&,const string &,bool (cons string &,const string&));
//equivalent declaration:explicitly define the parameter as a pointer to function
void useBigger(const string &,const string &,bool (*)(const string &,const string &))

5.返回指向函数的指针
函数可以返回指向函数的指针

// ff is a function taking an int and returning a fuction pointer
// the function pointed to returns an int and takes an int * and an int
int (*(int))(int *,int);

我们可以观察:
ff(int)
ff声明为一个函数,它带有一个int型的形参。该函数返回int ()(int ,int);
它(ff)是一个指向函数的指针,所指向的函数返回int型且带有int* 和int型的形参。
技巧:阅读函数指针声明的最佳方法是从生命的名字开始由里而外理解
使用typedef可使该定义更简明易懂:

//  PF is a pointer to a function returning an int,taking an int * and an int
typedef int (*PF)(int *,int);
PF ff(int); // ff returns a pointer to function

允许将形参定义为函数类型,但函数的返回类型则必须是指向函数的指针,而不能是函数。

typedef  int func(int*,int);
typedef  int(*PF)(int *,int);
PF ff(func); // ff returns a pointer to function

6.指向重载函数的指针
C++语言允许使用函数指针指向重载函数:

extern void ff(vector<double>);
extern void ff(usigned int);

//which function does pf1 refer to?
void (*pf1)(unsigned int) = &ff;  // ff(unsigned)

指针的类型必须与重载函数的一个版本精确匹配。如果没有精确匹配的函数,则对该指针的初始化或赋值都将导致编译错误:

// error:no match :invalid parameter list
void (*pf2)(int) = &ff;
//error:no match:invalid return type
double (*pf)(vector<double>);
pf3 = &&ff;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值