C++ 的名字查找(name lookup)

来源:互联网 发布:淘宝家居花瓶销售方案 编辑:程序博客网 时间:2024/04/29 01:59

这个是我学习C++以后一直不知道的一个方面知识,最近想回顾一下C++的基础知识,所以在看一本书。这本书中讲了这个关于名字查找这个部分我觉得很新奇。我就稍微总结一下。

 

什么是名字查找?

以我的感觉应该算是这样的吧,比如你调用了一个函数,编译器是怎么去寻找这个函数的定义的吧。这个就是所谓的名字查找的过程。先写一个程序来看看这个名字查找的运行过程吧!!!

 

这个程序的class A这个类定义在namespace test中,而<<  >>这两个操作符则定义在全局作用域中,运行结果发生编译提出了

很多莫名其妙的错误,最为主要的就是这句:

error: no match for 'operator>>' in '*((std::istream_iterator<test::A>*)this)->std::istream_iterator<test::A>::_M_stream >> ((std::istream_iterator<test::A>*)this)->std::istream_iterator<test::A>::_M_value'

 

大概可以理解为没有匹配的>>这个函数的意思吧。这就是疑问所在了,为什么我定义的流操作符在不能识别,却说没有找到匹配的函数呢。

 

这就是C++ 编译器中的名字查找的功能。

C++名字查找有两个方法

一个是OL(ordinary name lookup) 普通查找规则


一个是ADL(argument-depentment lookup)依赖于实参的名字查找


这两个查找规则就是C++的查找规则,如果经过这两个规则还是没有找过的话那编译器就会报出没有匹配函数这样的错误。OL这个规则是从相邻的作用域开始进行查找,如果没有找过的话,那就到更加大的一个作用域去进行查找,OL有这样的一个规则(OL terminates as soon as the name is found),也就是说当编译器在这个作用域中找到了与要找的函数名相同的时候,这就不再会到更加大的作用域中去寻找。也就说停止在这个地方了。如果存在有重载的问题,那编译器会在找到的这个作用域内的进行考虑,到底哪个函数才是最为匹配的,但是它不会往外层进行查找了。这就有可能会形成错误。

ADL规则的意思就是和字面意思差不多,编译器根据实参的类型,去包含着这些类型的名字空间中去查找我们所要的函数定义或者名字。如果是类的话,那就可能包含了它的本身还是他所有基类的名字空间,如果是模板类的话,那就是定义原型模板的名字空间和所有模板实参的名字空间。

分析上述程序的名字查找的过程,copy1(copy第一次调用)会调用>>这个操作符,编译器会把当作istream的成员函数,然后去istream的类中去寻找这个函数的名字,但由于istream只是对内定的数据类型是重载的,所有不是最佳的匹配,但是编译器还是在类的作用域中找到了这个名字,所以他不会去全局中去找。

然而编译器使用ADL规则也只是找到了名字空间std和test两个,但是我们自定义的这个流操作符却是定义在全局作用域中,所以最后会报错。

如果将自己定义的<< >>包含在test中的话,那就可以通过编译运行的。

 

所以将相关操作符的声明和主要类型放在同一个名字空间中非常重要的。不然编译器找不到他们的....

 

原创粉丝点击