一、函数重载
1、函数重载概念
函数重载是指在同一作用域中,具有不同形参列表(参数的 个数 或 类型 或类型顺序 不同)的同名函数。
C语言中不允许同名函数的存在,如果一个程序中有两个函数的函数名完全相同,就会报错。而C++中是允许同名函数的存在的。比如下面这段代码,在C语言中编译不过去,在C++中则可以编译通过:
void Swap(int* pa, int* Pb)
{;
}void Swap(double* pa, double* pb)
{;
}
2、构成函数重载条件
(1)在同一作用域中
只有在同一作用域中的函数,才可以构成重载。
以下两个函数构成函数重载:
namespace test_1 {void Swap(int* pa, int* Pb){cout << "void Swap(int* pa, int* Pb)" << endl;}void Swap(double* pa, double* pb){cout << "void Swap(double* pa, double* pb)" << endl;}
}
以下两个函数不构成函数重载:
namespace test_1 {void Swap(int* pa, int* Pb){cout << "void Swap(int* pa, int* Pb)" << endl;}
}
namespace test_2 {void Swap(double* pa, double* pb){cout << "void Swap(double* pa, double* pb)" << endl;}
}
在下面这个例子中,两个Swap函数虽然不构成函数重载,但是也是可以同时存在于程序中的,因为他们在不同的命名空间中,使用它们时需要用域作用限定符指定命名空间,变相的使函数名有了区别。如果在这段程序中同时展开了test_1和test_2这两个命名空间,重名使用这两个函数,程序也会出错。但是此时错误原因不是非法的函数重载,而是命名空间引用不明确,属于调用歧义:
(2)参数个数不同
void Swap(int* pa)
{cout << "void Swap(int* pa)" << endl;
}
void Swap(int* pa, int* pb)
{cout << "void Swap(int* pa, int* pb)" << endl;
}
(3)参数类型不同
void Swap(int* pa, int* pb)
{cout << "void Swap(int* pa, int* pb)" << endl;
}
void Swap(double* pa, double* pb)
{cout << "void Swap(double* pa, double* pb)" << endl;
}
(4)参数类型顺序不同
void Swap(char* pa, int* pb)
{cout << "void Swap(char* pa, int* pb)" << endl;
}
void Swap(int* pa, char* pb)
{cout << "void Swap(int* pa, char* pb)" << endl;
}
3、不构成函数重载
(1)返回类型不同
返回类型不同时,函数不构成重载关系。因为没有返回值的函数不需要变量来接收返回值,而有返回值的函数虽然会返回一个值,但是也可以不使用变量去接收它,所以会导致混淆,系统无法区分究竟需要调用哪个函数。
void Swap(int* pa, int* pb)
{cout << "void Swap(int* pa, int* pb)" << endl;
}
int Swap(int* pa, int* pb)
{cout << "int Swap(int* pa, int* pb)" << endl;
}
(2)与缺省参数结合
下面例子中的func函数也不构成重载关系,原因同样是调用歧义。
void func()
{;
}void func(int a = 10)
{;
}int main()
{func();return 0;
}
二、引用
引用,就是给一个已存在的变量取一个“别名”。编译器不会为这个引用变量开辟新的空间,它和它引用的变量共用同一块内存空间。
int a;
int& b = a;
int& c = a;
int& d = b;
可以给同一个变量取多个别名,也可以给别名再取别名。
b和c就是变量a的别名,d是引用变量b的别名。b、c、d本质上都是a的别名,他们的地址都和a保持一致。
引用变量的类型是 int& ,本质还是原先的变量,所以可以运用到函数传参当中:
void func(int& m, int& n)
{int tmp = m;m = n;n = tmp;
}int main()
{int x = 1, y = 0;func(x, y);printf("%d %d\n", x, y);return 0;
}
可以看到函数成功交换了x和y变量的值。
我们知道普通的传值调用是不会改变实参的值的,因为形参是实参的一份临时拷贝,形参和实参分别在不同的内存空间上,所以对形参的改变,并不会影响到实参。而通过引用,给实参取别名的方式,可以让形参称为实参的别名,这样,由于形参和实参共用了同一块内存空间,形参也就是实参,所以对形参的修改,也就成了对实参的修改,进而实现了上面例子中,对x、y变量的交换。
别名的这个特点,就使它有了许多指针的色彩,在许多情况下,可以用取别名的方式,来代替指针。
引用在定义的时候必须初始化,并且一旦指定了被引用的变量,就不可以再更换。
第9行的含义是把b变量的值赋给x变量,也就是a变量,而不是给x重新指定被引用的变量。
我们知道,在C语言中,如果用const修饰一个变量后,这个变量是不可以被直接改变值的,而我们可以通过使用指针,来由地址间接的去修改这个变量的值。然而在C++中,我们可不可以使用这样的方法改变被const修饰的变量的值,也不可以通过给它取别名,来改变它的值。
int main()
{const int a = 1;int* pa = &a;return 0;
}
int main()
{const int a = 1;int& y = a;return 0;
}
int main()
{const int a = 1;const int& y = a;y = 1;return 0;
}