名字查找

每当一个变量或者一个对象出现,编译器都会进行名字查找(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); // 编译器指出有多个函数重载匹配

C++:Name Lookup & Best Match的更多相关文章

  1. Mongodb:修改文档结构后出现错误:Element '***' does not match any field or property of class ***.

    Mongodb:修改文档结构后出现错误:Element '***' does not match any field or property of class ***. Mongodb是一种面向文档的 ...

  2. ElasticSearch查询 第四篇:匹配查询(Match)

    <ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...

  3. fastDfs V5.02 升级到 V5.08版本后,启动报错:symbol lookup error: /usr/bin/fdfs_trackerd: undefined symbol: g_current_time

    /libfastcommon-1.0.36 # ./make.sh cc -Wall -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -g -O3 -c -o hash.o ...

  4. Neo4j 第九篇:查询数据(Match)

    Cypher使用match子句查询数据,是Cypher最基本的查询子句.在查询数据时,使用Match子句指定搜索的模式,这是从Neo4j数据库查询数据的最主要的方法.match子句之后通常会跟着whe ...

  5. 记录一次(xheditor-1.1.6-zh-cn.min.js)的错误:Cannot read property 'match' of undefined的问题解决

    由于使用了xheditor富文本框,且这个版本是2011年开发的系统,当时只有IE8,所以一切正常. 但是问题来了,今天使用IE11测试和谷歌浏览器测试,发现一直报这个错误: 且google了一下,没 ...

  6. Python自动化报错:IndentationError-unindent does not match any outer indentation level

    ​从错误中了解python语法: 如下图: 这个是因为python语句块是由格式来控制(缩进): 解决: 出现这个问题需要看下,自己写的python语句块是否格式缩进的问题 例如:如下图:构造函数前面 ...

  7. IndentationError:unexpected indent”、“IndentationError:unindent does not match any outer indetation level”以及“IndentationError:expected an indented block Python常见错误

    错误的使用缩进量 记住缩进增加只用在以:结束的语句之后,而之后必须恢复到之前的缩进格式. 经典错误,一定要注意缩进,尤其是在非界面化下环境的代码修改

  8. 错误: symbol lookup error: /usr/local/lib/libreadline.so.6: undefined symbol: PC

    su - root mkdir temp mv /local/ldconfig  apt-get update

  9. python正则表达式模块re:正则表达式常用字符、常用可选标志位、group与groups、match、search、sub、split,findall、compile、特殊字符转义

    本文内容: 正则表达式常用字符. 常用可选标志位. group与groups. match. search. sub. split findall. compile 特殊字符转义 一些现实例子 首发时 ...

随机推荐

  1. vue组件定义方式,vue父子组件间的传值

    vue组件定义方式,vue父子组件间的传值 <!DOCTYPE html> <html lang="zh-cn"> <head> <met ...

  2. tensorflow slim代码使用

    此处纯粹作为个人学习使用,原文连接:https://www.jianshu.com/p/dc24e54aec81 这篇文章是借鉴很多博文的,作为一个关于slim库的总结 导入slim模块 import ...

  3. CSP-S 爆零记

    抱歉,这么晚才更. 事实是:我都没有去 所以爆零了 QwQ

  4. WebSocket数据加密——AES与RSA混合加密

    前言 之前在写“一套简单的web即时通讯”,写到第三版的时候没什么思路,正好微信公众号看到一篇讲API交互加密,于是就自己搞了一套AES与RSA混合加密,无意中产生应用在WebSocket想法,好在思 ...

  5. 【git】代码回退指定commit

    [注意:如果提交的错误代码较少,可以在本地修改成 commit之前的正确代码样子,然后再提交一次即可.不用麻烦的操作回滚.] 开发人员错误将代码提交到gitlab的远程dev分支,回滚方法如下: 1. ...

  6. vue 地图可视化 maptalks 篇

    Maptalks 项目是一个 HTML5 的地图引擎, 基于原生 ES6 Javascript 开发: - 二三维一体化地图, 通过二维地图的旋转 /倾斜增加三维视角 - 插件化设计, 能与其他图形库 ...

  7. MySQL 主从复制开启 GTID

    GTID (Golobal Transaction ID) 是对于一个已提交事务的唯一编号,并且是一个全局(主从复制)唯一的编号. GTID 复制和传统复制的区别:在启动主从复制时,不需要指定 bin ...

  8. qt md5加密,base64编码解码

    qt md5加密,base64编码解码 md5加密 QByteArray data = "12121221"; data += "asdfas"; QByteA ...

  9. Linux命令: cat

    -s  连续多个空行显示为一个空行. -n 给每一行前显示行号. -b 只给非空行前显示行号. -E  在每行后显示一个$ cat f - g  把文件f的内容.STDIN.文件g的内容连接起来 .

  10. SpringBoot2.x项目pom.xml第一行报错

    原来使用的是2.1.4 后来改成2.1.3 保存自动从新下载就好了    毕竟使用人数多 maven地址:https://mvnrepository.com/artifact/org.springfr ...