补充C++基础笔记。
函数 part 2:函数重载、特殊用途语言特性、函数匹配、函数指针
函数重载
定义:如果同一作用域内的几个函数名字相同但形参列表不同,我们称之为重载函数 -> 编译器会根据传递的实参类型推断想要的是哪个函数
- 几对无法区分的重载函数
(1) 除返回类型外其他所有要素都相同的两个函数;
(2) 形参仅仅是名字不同;
(3) 拥有顶层const的形参 v.s 没有顶层const的形参;
如:
Record lookup(Phone);
Record lookup(const Phone); //重复声明了Record lookup(Phone)
Record lookup(*Phone);
Record lookup(Phone* const); //重复声明了Record lookup(Phone*)
但是能区分底层的:
Record lookup(Account&); //函数作用于Account的引用
Record lookup(const Account&); //新函数,作用于常量引用
Record lookup(Account*); //新函数,作用于指向Account的指针
Record lookup(const Account*); //新函数,作用于指向常量的指针
- const_cast和重载:调用返回值是const的函数时,使用const_cast去掉const
//比较两个string对象的长度,返回较短的那个引用
const string &shortString(const string &s1, const string &s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
//非常量返回值的调用
const string &shortString(const string &s1, const string &s2)
{
auto &r = shortString(const_cast<const string&>(s1), const_cast<const string&>(s2));
return const_cast<string&>(r);
}
特殊用途语言特性
默认实参
- 给定的作用域中一个形参只能被赋予一次默认实参。
// 表示高度和宽度的形参没有默认值
string screen(sz, sz, char = ' ');
string screen(sz, sz, char = '*'); //错误:重复声明
string screen(sz = 24, sz = 80, char); //正确,添加默认实参
- 局部变量不能作为默认实参。
内联函数和constexpr函数:通常定义在头文件内
- 将函数指定为内联函数,可以将类似
cout << shorterString(s1, s2) << endl
在编译过程中展开为类似cout << (s1.size() < s2.size() ? s1 : s2) << emdl
的形式,从而消除shorterString函数的运行开销。
内联机制用于优化规模较小、流程直接、频繁调用的函数 – 内联说明可以选择忽略这个请求。 - constexpr函数:指能用于常量表达式的函数。
约定:函数的返回值及所有形参的类型都得是字面值类型,而且函数体中必须有且只有一条return语句。
constexpr int new_sz() { return 42; }
constexpr int foo = new_sz(); //正确:foo是一个常量表达式
constexpr被隐式地指定为内联函数。
constexpr函数体内也可以包含其他语句,只要这些语句在运行时不执行任何操作就行。
//如果arg是常量表达式,则scale(arg)也是常量表达式
constexpr size_t scale(size_t cnt) { return new_sz() * cnt; }
int arr[scale(2)]; //正确:scale(2)是常量表达式
int i = 2; //i不是常量表达式
int a2[scale(i)]; //错误:scale(i)不是常量表达式
调试帮助:assert和NDEBUG
- assert预处理宏:定义在cassert头文件中
assert(expr)
对expr求值,如果表达式为假,assert输出信息并终止程序地执行,否则assert什么也不做。 - NDEBUG预处理变量:定义了NDEBUG,则assert什么也不做。
函数匹配
步骤一:确定候选函数和可行函数:
候选函数:与被调用的函数同名+声明在调用点可见
可行函数:形参数量与本次调用提供的实参数量相等+每个实参的类型与对应的形参类型相同
步骤二: 寻找最佳匹配(如果有的话)
函数指针
函数指针指向的是函数而非对象。
bool lengthCompare(const string &, const string &);
bool (*pf) (const string &, const string &); //未初始化
使用函数指针
把函数作为一个值使用时,该函数自动转换成指针:
pf = lengthCompare; //pf指向名为lengthCompare的函数
pf = &lengthCompare; //等价的赋值语句:取地址符可选
参考资料:
- C++ primer. 第五版.