1. 函数重载
1.1 默认参数
C++新增的默认参数指的是函数调用省略实参时自动调用的一个值。
通过函数原型设置函数的默认参数,函数定义与没有默认参数时完全相同。如以下函数原型:
char * left(const char * str, int n = 1);
调用时如果省略参数n,则它的值将为1;否则传入的值将覆盖默认值。
对于带参数列表的函数,必须从左到右添加默认值,即要为某个参数设置默认值,必须为它右边的所有参数提供默认值。
int harpo(int n, int m = 4, int j =5); // 正确
int chico(int n, int m = 6, int j); // 错误
int groucho(int k = 1, int m = 2, int n = 3); // 正确
调用时,实参从左到右的顺序依次赋值给相应的形参,不能跳过任何参数。如以下调用错误:
beeps = harpo(3, ,8);
默认参数只是提供了一种便捷方法,在定义类时可以减少需要定义的析构函数、方法以及方法重载的数量。
以下程序使用了默认参数。
#include <iostream>
const int ArSize = 80;
char * left(const char * str, int n = 1);
int main()
{
using namespace std;
char sample[ArSize];
cout << "Enter a string:\n";
cin.get(sample, ArSize);
char * ps = left(sample, 4);
cout << ps << endl;
delete [] ps;
ps = left(sample);
cout << ps << endl;
delete [] ps;
return 0;
}
// 返回一个新的字符串,包含原字符串的前n个字符
char * left(const char * str, int n)
{
if(n < 0)
n = 0;
char * p = new char[n+1];
int i;
for(i = 0; i < n && str[i]; i++)
{
p[i] = str[i];
}
while (i <= n)
{
p[i++] = '\0';
}
return p;
}
其中left函数用于返回传入字符串的前n个字符的新字符串。left函数中使用了new分配的内存,因此在调用完毕后需要使用delete进行释放。
1.2 函数重载
函数重载是指设计一类函数名相同,但使用不同参数列表的函数,C++根据上下文确定使用的重载函数版本。
函数重载的关键是参数列表,也称为特征标。如果两个函数的参数数目与类型相同,排列顺序也相同,则它们的特征标相同,与变量名无关。
C++允许定义同名但特征标不同的函数。(与C语言不同)
如定义一组原型如下的print函数:
void print(const char * str, int width); // #1
void print(double d, int width); // #2
void print(long l, int width); // #3
void print(int i, int width); // #4
void print(ocnst char* str); // #5
使用print函数时,编译器根据用法选择具有相应特征标的原型:
print("Pancakes", 15); // 使用#1
print("Syrup"); // 使用#5
print(1999.0, 10); // 使用#2
print(1999, 12); // 使用#4
print(1999L, 12); // 使用#3
如果编译器找不到匹配的特征标,会尝试进行强制转换以匹配函数原型。
例如以下调用:
unsigned int year = 3210;
print(year, 6);
如果#2为print函数唯一的原型,则函数调用会将year转换为double类型。但由于上面有3种函数原型将数字作为第一个参数,有3种可能的转换方式,这种情况下C++会报错。
编译器在检查函数特征标时,将类型引用和类型本身视为同一个特征标。如以下两个原型:
double cube(double x);
double cube(double & x);
对于重载函数,特征标必须不同。如以下函数声明是互斥的:
long gronk(int n, float m);
double gronk(float n, float m);
C++不允许这样进行重载。返回类型可以不同,但特征标必须不同。
以下的代码中使用了重载函数left。重载的left函数参数为数字,返回数字的前几位。使用n /= 10的方式来计算传入参数的位数,同样也可以用来去掉数字的后几位。
#include <iostream>
unsigned long left(unsigned long num, unsigned ct);
char * left(const char * str, int n = 1);
int main()
{
using namespace std;
char * trip = "Hawaii!!";
unsigned long n = 12345678;
int i;
char * temp;
for(i = 1; i < 10; i ++)
{
cout << left(n, i) << endl;
temp = left(trip, i);
cout << temp << endl;
delete [] temp;
}
return 0;
}
unsigned long left(unsigned long num, unsigned ct)
{
unsigned digits = 1;
unsigned long n = num;
if(ct == 0 || num == 0)
{
return 0;
}
while(n /= 10)
{
digits ++;
}
if(digits > ct)
{
ct = digits - ct;
while(ct --)
{
num /= 10;
}
return num;
}
else
{
return num;
}
}
char * left(const char * str, int n)
{
if(n < 0)
{
n = 0;
}
char * p = new char[n+1];
int i;
for(i = 0; i < n && str[i]; i++)
{
p[i] = str[i];
}
while(i <= n)
{
p[i++] = '\0';
}
return p;
}
运行结果: