0
点赞
收藏
分享

微信扫一扫

C++:01---函数重载、缺省参数

一、函数重载

  • 概念:在同一作用域内,声明几个功能相同(或类似)的同名函数,实现功能类似但所处理数据类型不同的函数
  • 函数重载的条件
  • 函数名必须相同
  • 函数的参数不同(参数个数不同或参数对应位置的数据类型不同)
  • 作用域必须相同
  • 函数重载与函数的返回值无关

哪些情况不构成重载、构成重载

  • ①顶层const不构成重载,所以下面的两个函数不构成重载

int add(int a,int b); int add(const int a,const int b);

  • ② 普通引用不构成重载所以下面的两个函数不构成重载

int add(int a,int b); int add(int& a,int& b);

  • ③常量引用或者常用指针构成重载,所以下面两组函数都构成重载(因为const对象不能转换为其它类型,所以只能将const对象传递给const形参。相反,非常量对象可以传递给任何类型,所以非const对象都可以传递给下面4个函数)

int add(int* a,int* b); int add(const int* a,const int* b);int add(int& a,int& b); int add(const int& a,const int& b);

  • ④ const函数与非const函数构成重载

int add(int a,int b); int add(int a,int b)const;

函数重载与数据类型之间的关系

  • 在书写函数时,我们要确定自己的需求。如果形参的数据类型没有设置好,编译器会报错

案例一:

  • 下面的add(3.1,4.25)函数参数为double类型,调用此函数时,编译器没有找到有double类型的函数,于是就去类型转换寻找适合的函数,发送double可以转换为int,也可以转换为float。于是产生二义性,程序报错
  • 但是可以通过在数字后面给出F或者强制类型转换来告诉编译器具体调用哪一个函数

int add(int a,int b); float add(float a,float b); int main() { add(1,2); add(3.1,4.25);//报错 add(3.1F, 4.25F);//正确 add((float)3.1,(float)4.25);//正确 }

  •  例如:下面的3.14会转换为float也会转换为long,因此也报错

int func(long a); int func(float a); int main() { func(3.14);//报错
}

案例二:

  • 下面的func函数调用也会产生二义性
  • 第一步:调用func时,参数1为int,此时func去匹配两个重载函数,发现int func(int a,int b);比较合适,于是就调用此函数
  • 第二步:匹配到参数2时,3.14为double类型,编译器发现int func(double a,double b);比较合适,于是就调用此函数
  • 最后,编译器产生二义性报错

int func(int a,int b); int func(double a,double b); int main() { func(1, 3.14); //报错 }

案例三:

  • 常量形参与非常量形参的调用(上面,介绍过常量形参与非常量形参形成重载)
  • 执行func(a);时,因为a为非常量,因此两个函数都可以调用。但是因为把非常量赋值给常量需要强制类型转换,因此就调用int func(int &s);
  • 执行func(b);时,传入的b是const类型,因此不能把普通引用绑定到const对象上,所以只调用int func(const int &s);
  • 常量指针的原理也是如此(详情见const讲解文章)

int func(int &s); int func(const int &s); int main() { int a = 10; const int b = 20; func(a); //调用int func(int &s); func(b); //调用int func(const int &s); }

函数重载示例代码 

struct myPoint { int row, col; }; myPoint add(myPoint a, myPoint b) { myPoint tempPoint; tempPoint.col = a.col + b.col; tempPoint.row = a.row + b.row; return tempPoint; } int add(int a, int b) { return a + b; } double add(double a, double b) { return a + b; } int main() { cout << add(1, 2) << endl; //3 cout << add(2.5,3.1) << endl; //5.6 return 0; }

函数重载与作用域的关系

  • 下面的代码不规范(不应该在一个函数中声明一个函数)。但是只是为了函数重载与作用域的关系

string read(); void print(const string&); void print(double); int main() { bool read = false; int val = 1; string s = read(); //错误,read函数与局部变量read冲突
void print(int); //定义一个参数为int的print函数 print("Value"); //错误,print(const string&);被隐藏 print(val); //正确,调用print(int) print(3.14); //正确,调用print(int) }

const_cast与重载

  • const_cast介绍
  • 功能:用来将对象的常量性移除
  • 注意事项:
  • 只能改变运算对象的底层const
  • const_cast只能改变表达式的常量属性,而不能改变表达式的数据类型
  • const_cast常用于有函数重载的上下文

演示案例


  • 当我们去掉某个对象的const性质之后,编译器就不再阻止我们对该对象进行写操作了,因此写操作会产生未定义的后果
  • const char *pc;

  • //正确,但是通过p写值是未定义的行为
  • char *p = const_cast<char*>(pc);
  • 底层const对象转换为非const对象

二、缺省参数(默认实参)

  • 概念:人为的为函数定义一个或多个默认参数,在调用函数时,它们被赋予一个相同的值
  • 注意事项:
  • 如果函数没有声明,则默认形参直接写在函数定义时
  • 如果函数有声明和定义,则默认形参只可写在函数声明中,函数定义时不可以写
  • 默认形参只能写在最后,或其及其后面都是默认形参
  • 缺省参数是在编译阶段决定的,所以只能用常量或者全局变量作为缺省参数
  • 函数调用时给出实参,会覆盖掉默认参数

缺省参数示例代码

int add(int a, int b,int c=10) { return a + b+c; } int main() { cout << add(1, 2) << endl; //13 cout << add(1,2,50) << endl; //53 return 0; }

使用全局变量初始化缺省参数

  • 缺省参数可以使用一个函数外的变量/常量初始化。但是不能用函数内的局部变量初始化

int a=10; int b=20; char c='a'; void func(int num1=a,int num2=b,char s=c);

  • 注意事项:虽然可以用全局变量初始化缺省参数,但是如果全局变量被改变了,再次调用这个函数缺省参数的值也会改变

int a=10; int b=20; char c='a'; void func2() { a=66; //改变全局变量 int b=30; //局部变量,但是不影响全局变量 func(); //调用func(66,20,'a'); }

函数的调用

  • 原理:使用的函数逐个入栈,main函数中调用到某函数时,跳到栈对应的函数位置,并返回结果
  • 普通函数的调用与内联函数的内存模型

三、函数重载冲突

  • 函数重载与缺省参数冲突的特殊情况

int add(int a, int b,int c=10)

{

return a + b+c;

}

int add(int a, int b)

{

return a + b;

}

int main()

{

cout << add(1, 2) << endl;//报错,对函数的调用不明确

return 0;

}

 


举报

相关推荐

0 条评论