名字查找

每当一个变量或者一个对象出现,编译器都会进行名字查找(name lookup),以确认这个变量或对象的具体属性。一般情况下,程序会从变量出现的地方开始向上查找,由内向外查找各级作用域直到全局作用域,找到同名的变量声明即停止,若最终没找到则报错。

#include <iostream>
using namespace std; int a = 0; int main() {
string a = "1";
cout << a << endl; // 在main函数体内找到了a的声明,停止名字查找,输出为string的内容“1”
return 0;
}

名字查找还受到作用域限定符::的影响,若变量之前出现了作用域限定,那么则会从限定的作用域内进行全局搜索,并且不会查找其他位置。如果::之前没有出现作用域名,那么就会在全局作用域查找。

#include <iostream>
using namespace std; int a = 0; int main() {
string a = "1";
cout << ::a << endl; // 限定a的查找从全局作用域开始,那么首先被找到的是a的int类型定义,程序输出0
return 0;
}

此外,由于在找到同名声明之后便会停止查找,函数匹配出现在名字查找之后

#include <iostream>
using namespace std; void print() { cout << "1" << endl; } int main() {
int print;
print(); // 试图调用print(),但程序无法通过编译,这是因为在找到int型变量print之后,
// 编译器就停止了查找,把一个变量当作函数调用显然是错误的
return 0;
}

名字隐藏

从上面的例子可以看出,在不使用访问限定符的情况下,内层作用域的变量会隐藏外层作用域的同名变量,即发生了名字隐藏。名字隐藏还会发生在类的继承过程,在子类定义和父类同名的成员时,会隐藏从父类继承来的成员,名字隐藏并不是什么特性,相反,名字隐藏会增加程序编写的难度。我们应该养成良好的命名习惯,避免出现名字隐藏

最佳匹配

在函数调用时,首先对函数进行名字查找,在找到一个同名函数(假设不会出现命名冲突)时,编译器并不会停止查找,而是继续找出当前作用域的所有重载函数,然后根据最佳匹配规则,确定实际调用的函数。不同作用域的同名函数并不会被视为重载。最直观的例子是,类内的函数与类外的同名函数并不会形成重载。

在名字查找完成且不存在编译错误的情况下,编译器便开始确定与调用匹配得最好的函数。最佳匹配原则也很简单,实参类型与形参类型越接近,匹配得越好。

void print(int a) { cout << "int" << endl; }

void print(double a) { cout << "double" << endl; }

print(1); // 1是int类型,与print的int形参重载构成最佳匹配,故程序输出“int”

但如果同时有多个函数与调用形成匹配,那么编译器将报错。编译器不允许有二义性的调用存在。

void print(int a, int b, int c) { cout << "int" << endl; }

void print(double a, double b, double c) { cout << "double" << endl; }

print(1, 1.0, 1); // 编译器指出有多个函数重载匹配

最新文章

  1. Visual Studio 2015 开发 ASP.NET 5 有何变化?
  2. Java 项目优化实战
  3. 类集-collection接口
  4. 递归函数 Python
  5. 通过List&lt;String&gt;动态传递参数给 sqlcommand.Parameters
  6. 第四章 在MVC4.0中对脚本以及样式表的引用变化
  7. yum_rpm(利用dvd建立本地yum库)
  8. jquery easyui-linkButton获取和设置按钮text并且解决火狐不支持innerText的方法
  9. Trail: JDBC(TM) Database Access(2)
  10. javaweb学习总结二(静态导入、自动拆装箱、增强for与可变参数)
  11. C# 判断某程序是否运行
  12. SQL排序 空值的后面
  13. iOS 数组里面取字典的值
  14. Android5.0 Gallery2上编译Gallery模块出错
  15. PMP知识点(二)——三点估算的两种方法对活动持续时间估算的影响和如何取舍
  16. Gym - 101755G Underpalindromity (树状数组)
  17. HDFS数据节点DataNode未启动解决方法
  18. 网络(socket)编程
  19. zookeeper安装Linux
  20. javaScript 数组迭代方法

热门文章

  1. 【总结】《氨基酸新晋管理者领导力培训》第一次课_Day2_学习心得
  2. github上星星1万多的python教程推荐收藏
  3. 关于.Net Core 部署在Linux下连接SqlServer数据库超时解决办法
  4. C#委托内部使用局部的变量的问题
  5. jdk api 1.6,1.7,1.8,1.9版本(中文)
  6. IOC控制反转、Unity简介
  7. tableView左划自定义带图片按钮
  8. SwiftUI学习(二)
  9. iOS 应用程序启动时要做什么
  10. Gradle在Android中的简单使用