6.4 函数重载
如果同一作用域内的几个函数名字相同但形参列表不同,称之为重载(overload)函数。
tips:
- 不允许两个函数除了返回类型外其他所有的要素都相同。
- 一个拥有顶层
const
的形参无法和另一个没有顶层const
的形参区分开来。
Record lookup(Phone);
Record lookup(const Phone); // 一样的
- 如果形参是某种类型的指针或引用,则通过区分其指向的是常量对象还是非常量对象可以实现函数重载,此时的const是底层的
Record lookup(Account&);
Record lookup(const Account&); // 新函数,作用于常量引用
注意:当传递一个非常量对象或者非常量对象的指针时,编译器会优先选用非常量版本的函数
const_cast和重载
const string& shorterString(const string& s1, const string& s2) {
return s1.size() < s2.size() ? s1 : s2;
}
这里返回常量引用,当传入非常量对象时,需要一个非常量的版本,返回非常量引用
string& shorterString(string& s1, string& s2) {
auto& r = shorterString(const_cast<const string&> s1, const_cast<const string&> s2);
return const_cast<string&> (r);
}
先把非常量引用转为常量引用,调用常量引用版本的函数,再把返回的常量结果转为非常量
6.5 特殊用途语言特性
6.5.1 默认实参
注意:一旦某个形参被赋予了默认值,它后面的所有形参都必须有默认值
在给定的作用域中一个形参只能被赋予一次默认实参,不能重复声明
string screen(int, int, char = ' ');
string screen(int, int, char = '*'); // 错误:重复声明
局部变量不能作为默认实参,只要表达式的类型能转换为形参所需要的类型,该表达式就能作为默认实参
int ht();
int wd = 80;
char def = ' '; // 全局变量
string screen(int = ht(), int = wd, char = def);
string window = screen(); // 调用screen(ht(), 80, ' ');
如果是在函数作用域里面
void fun2() {
def = '*'; // 修改了全局变量def
int wd = 100; // 局部变量不影响全局变量
window = screen(); // 调用screen(ht(), 80, '*');
}
6.5.2 内联函数和constexpr函数
内联函数可避免函数调用的开销,将函数指定为内联函数(inline),通常就是将它在每个调用点上“内联地”展开
inline const string &horterString(const string &s1, const string &s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
在函数声明和定义中都能使用关键字inline
,但是建议只在函数定义时使用
一般来说,内联机制适用于优化规模较小、流程直接、调用频繁的函数。内联函数中不允许有循环语句和switch
语句,否则函数会被编译为普通函数
constexpr
函数是指能用于常量表达式的函数。constexpr
函数的返回类型及所有形参的类型都得是字面值类型。另外C++11标准要求constexpr
函数体中必须有且只有一条return语句,但是此限制在C++14标准中被删除
constexpr int new_sz()
{
return 42;
}
constexpr int foo = new_sz(); // ok: foo是常量表达式
constexpr
函数被隐式地指定为内联函数