[C++] 函数重载
函数重载
如果同一作用域内的几个函数名字相同但形参列表不同,我们称之为重载函数。
void print(const char *cp); void print(const int *beg, const int *end); void print(const int ia[], size_t size); int j[2] = {0,1}; print("Hello World!"); print(j, end(j) - begin(j)); print(begin(j), end(j));
main函数不能重载
对于重载函数来说,它们应该在形参数量或形参类型上有所不同。
不允许两个函数除了返回类型外其他所有的要素都相同。
有时候两个形参列表看起来不一样,实际上是相同的
int calc(const int &a); int calc(const int&);
形参名只是起到了帮助记忆的作用。有没有它并不影响形参列表的内容
重载和const形参
顶层const不影响传入函数的对象。一个拥有顶层const的形参无法和另一个没有顶层const的形参区分开
Record lookup(Phone); Record lookup(const Phone); // const Phone为顶层const、 Record lookup(Phone*); Record lookup(Phone* const);
// Phone* const为顶层const
以上函数存在重复声明
如果形参是某种类型的指针或引用,则通过区分其指向的是常量对象还是非常量对象可以实现函数重载,此时const是底层的
Record lookup(Account&); // 函数作用域Account的引用 Record lookup(const Account&); // 函数作用于常量引用 Record lookup(Account*); // 作用于指向Account指针 Record lookup(const Account*); // 作用于指向常量的指针
我们只能把const对象传递给const形参,
相反的,非常量可以转换成const
所以以上4个函数都能作用于非常量对象或者指向非常量对象的指针。
当我们传递一个非常量对象或者指向非常量对象的指针使,编译器会优先选用非常量版本的函数。
const_cast和重载
比较两个string对象的长度,并返回较短的那个引用
const string &shorterString(const string &s1, const string &s2) { return s1.size() < s2.size() ? s1 : s2; }
我们可以对两个非常量的string实参调用这个函数,但返回的结果是const string的引用。
所以我们需要一个新的函数,当实参不是常量时,得到的结果是一个普通的引用。可以使用const_cast完成。
string &shorterString(string &s1, string &s2) { auto &r = shorterString(const_cast<const string>(s1), const_cast<const string>(s2)); return const_cast<string&>(r); }
首先将实参强制转换成对const的引用,然后调用shorterString的const版本,const版本返回对const string的引用,然后将其转换成一个普通的string&。
重载与作用域
一般来说,将函数声明置于局部作用域内不是一个明智的选择。
重载对作用域的一般性质并没有改变,如果我们在内层作用域中声明名字,它将隐藏外层作用域中声明的同名实体。在不同作用域中无法重载函数名
在作用域中调用函数时,编译器首先寻找对该函数名的声明,一旦在该作用域内找到所需名字,编译器会自动忽略外层作用域中的同名实体。剩下来就是检查函数调用是否有效了。
在C++中,名字查找在类型检查之前
string read(); void print(const string &); void print(double); void fooBar(int ival) { bool read = false; // 新作用域,隐藏了外层read函数 string s = read(); // 错误,read是bool类型变量 void print(int); // 在作用域内声明函数 print("Value: "); // 错误,作用域内只有print(int),外层print被隐藏 print(ival); // 正确,调用当前print(int) print(3.14); // 正确,调用当前print(int). }
void print(const string &); void print(double); void print(int); void fooBar2(int ival) { print("Value: "); // 重载调用 print(ival); // 重载调用 print(3.14); // 重载调用,void print(double) }
void print(const string &); void print(double); void print(int); void fooBar2(int ival) { print("Value: "); // 重载调用 print(ival); // 重载调用 print(3.14); // 重载调用,void print(double) }