该文为中国大学MOOC上北京邮电大学崔毅东和杨谈老师主讲的《C++程序设计(面向对象进阶)》笔记整理
1. 变量的作用域
- 作用域的分类
-
全局作用域:全局变量
-
局部作用域:局部分类
如果外部代码块和内嵌代码块有同名变量,那么会产生同名覆盖,此时遵循"就近原则"
-
一元作用域解析运算符
当局部变量与全局变量相同时,可使用 :: 访问全局变量,该运算符被称为一元作用域解析运算符
#include<iostream> int i = 10; int main() { int i = 5; for (int i = 0; i < 4; i++) { std::cout << i << std::endl; // 访问的是 for 循环中的 i std::cout << ::i << std::endl; // 访问的是全局变量 i,而不是 for 前面的 i } return 0; }
2. 重载函数
重载函数是在同一个名字空间中存在两个或多个具有相同名字的函数所构成的语法现象
调用重构函数的语句,是编译器在编译期确定的
编译器确定重构函数的依据是函数参数的类型、个数和次序,无法根据函数的返回值判断
如果编译器无法判定,就会报告二义性错误
#include<iostream>
auto max(int a, int b) {
return a > b ? a : b;
}
auto max(double a, double b) {
return a > b ? a : b;
}
int main() {
std::cout << max(4,2) << std::endl; // 调用第一个 max
std::cout << max(4.5, 2.2) << std::endl; // 调用第二个 max
return 0;
}
3. 带有默认值的函数
函数的参数可以指定默认值
指定默认值时,要保证带默认值的参数位于函数列表的右侧
int max(int a,int b = 1,int c); // error
int max(int a,int b = 1,int c = 1); // correct
调用带有默认值的函数时,如果不指定带有默认值的参数,则该参数自动被赋为默认值
#include<iostream>
auto max(int a, int b = 1) {
return a > b ? a : b;
}
int main() {
std::cout << max(4, 2) << std::endl; // 传入参数 b=2
std::cout << max(5) << std::endl; // 未对b传参,b 默认为1
return 0;
}
函数声明有默认参数,函数实现时不需要带默认参数
#include<iostream>
int max(int a, int b=5);
int main() {
std::cout << max(2,6) << std::endl;
std::cout << max(3) << std::endl;
return 0;
}
int max(int a, int b ) { // 如果此处给 b 赋默认值,报错
return a > b ? a : b;
}
函数重载时,不允许定义默认参数
#include<iostream>
void max(int a = 1) {
std::cout<<a<<std::endl;
}
void max(double a = 1.4) {
std::cout << a << std::endl;
}
int main() {
max(3);
max(); // error,对重载函数的调用不明确
return 0;
}
4. 内联函数
-
普通函数的优缺点
- 优点:易读易维护
- 缺点:调用时有开销
- 函数调用时:参数及部分 CPU 寄存器的内容进栈,控制流跳转
- 函数返回时:返回值及寄存器值出栈,控制流跳转
-
使用内联函数
- 目的:减小函数调用开销
- 方法:代码插入到调用处
- 结果:程序变大
-
内联函数的声明
在普通函数前面加上 inline 关键字
inline int max(int a, int b) { return a > b ? a : b; }
-
调用内联函数
和调用普通函数写法相同
int x = max(3,6); int y = max(0,8);
-
内联展开
编译器实际在调用内联函数的情况
int x = (3 > 6 ? 3 : 6); int y = (0 > 8 ? 0 : 8);
-
内联函数的使用
常用场景:适用于频繁调用的短函数
inline 关键字,只是对编译器的一个请求,内联函数是否展开,由编译器决定