撒比的面向对象程序设计...这玩意有什么用处...
CSDN上所有的重载都讲的跟shit一样, 所以我开始好好写一个详细的, 以后看这个就足够了
首先记住几句废话:
1.同一个作用域下
2.函数名称相同
3.函数参数类型不同或者参数个数不同或者参数顺序不同
详细点说就是:
1. 函数参数的个数(一眼就能看出来), *参数类型*, const修饰(底层), 异常抛出(不用会, 知道就行), 不完全相同.
2. 返回类型(void, int, double, 以及void const和void)不能作为区分标志(二义性)
3. 缺省值不行(二义性)
4. 值类型参数的const型与非const型不作为区分标志(那其他的呢!!!!!)
5. 引用和指针类型参数, 是否可以改变实参, 可以! 能! 作为! 区分标志!!!!!
6. 二义性问题
我们所有的代码都省略#include<iostream>和using namespace std;
这样就差不多了, 现在我们开始解决问题.
*: 参数类型不同
你以为考试考的:
void f(int, float)
{
cout << 1;
}
void f(float, int)
{
cout << 2;
}
但是...
void f(double, float)
{
cout << 1;
}
void f(float, double)
{
cout << 2;
}
给你三分钟思考一下这玩意能不能运行.
3
2
1.
好, 其实, 它能, 好吧, 其实他也不能.
这里最理想的调用方式是类似于 f(2, 2.1); 这里float理所当然的选择了2, 当然double对应了精度高一些的2.1. 但是如果 你用了 f(2, 2) 或者 f(2.1, 2.1); 这样的调用方式, 编译器会直接报错. float和double根本找不到与谁对应, 然后你就明白什么是二义性了.
于是乎你发现你对二义性似乎一直有一些误解: 无论你最终如何调用这几个(同名函数之一)的函数, 只要有一个可以发生重载, 那么我们就认为重载合法.这一点非常重要.也就是说, 当我们判断函数合法重载的时候, 只需找出一条合理的调用方式, 就可以证明他的正确性, 而不是费尽心思的找到个反例
明白这一点之后我们对const的重载问题(引用我待会再说)就方便的多.
首先说返回值类型不能作为重载标志, 那么...
const int f(int)
{
cout << 1;
}
int f(int)
{
cout << 2;
}
行吗?
这次无论如何都不行. 这里const修饰了返回值. 返回了int和const int类型
值类型参数的const型与非const型不作为区分标志
其实重点是, const修饰指针(底层顶层)和const引用及const修饰成员函数的事情, 我们先把最基础的搞定.
那么...
void f(const int)
{
cout << 1;
}
void f(int)
{
cout << 2;
}
行吗?
不行. 虽然你的编译器不会显示任何红线, 但是就是不行. 无论你用f(2), int a;f(a) 或者const int a;f(a);都不行. 报错为: void f(const int)已有主体. 这句话我待会解释, 你先记住, 值类型参数的const型与非const型不作为区分标志
引用和指针类型参数, 是否可以改变实参作为区分标志
我们说过要找的是一条正确的调用方式而不是反例. 这里有一些合法的例子, 可以参考一下:
void fun();
void fun()const; //仅在类成员函数里使用啊
int fun(int&)
int fun(const int&)
int fun(int*);
int fun(const int*);//顶层指针
这些都是合法的.
那么...
int fun(int*);
int fun(int* const);
不行. 这里const是顶层const, 他修饰的是指针本身, 至于指向的变量, 仍然可以改变, 这里没有做到以是否能改变实参为区分标志.
二义性问题
很简单, 一眼就能看出来
int fun(int);
int fun(int&);
int fun (int a, int b=10);
int fun (int a);