免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2283 | 回复: 9
打印 上一主题 下一主题

为什么没有形成重载呢? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-02-21 14:38 |只看该作者 |倒序浏览
在NA中使用using namespace NA1;,为什么没有产生重载呢?
  1. #include <iostream>
  2. using namespace std;


  3. namespace NA1{
  4.         void print(int){cout<<"NA1::print(int)"<<endl;};
  5.         void print(const char*){cout<<"NA1::print(const char*)"<<endl;};
  6. }
  7. namespace NA{

  8.         using namespace NA1;
  9.         void print(const char*){cout<<"NA::print(const char*)"<<endl;};//这个没有和NA1中的重载,为什么?
  10.         void f(){
  11.                 print("Value:");
  12.                 //print(12);
  13.         };
  14. };

  15. int main(void){
  16.         NA::f(); //输出NA::print(const char*)

  17. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2012-02-21 15:07 |只看该作者
这个和C++名字查找顺序有关系:
1、编译器首先在空间NA中查找,看看能不能找到名字是print的函数,结果找到了,于是编译器就不在空间NA之外再查找是否有名字是print的函数了,查找到此结束。
2、编译器把所有NA空间里名字是print的函数列出来,挨个比较各个print函数的参数列表,看看有没有是const char*的,结果找到一个(如果找到两个或以上,就报错,有二义性,编译器蒙了)
3、如果NA中没有名字是print的函数,就在空间NA1里找(因为using namespace NA1使得空间NA1在空间NA中可见,NA1包含了NA,NA是NA1的子集)
4、如果把using namespace NA1改成 using NA1::print,就把空间NA1里的名字print引入了NA,重新编译的时候,编译器在空间NA1里发现了2个参数列表是const char*的print,于是报错二义性。

论坛徽章:
0
3 [报告]
发表于 2012-02-21 15:16 |只看该作者
那么,下面这个代码为什么可以形成重载呢?

  1. #include <iostream>
  2. using namespace std;

  3. namespace NA1{
  4.         void print(const char*){cout<<"NA1::print(const char*)"<<endl;}
  5.         void print(double){cout<<"NA1::print(int)"<<endl;}
  6. }

  7. void print(double){cout<<"print(double)"<<endl;}
  8. using namespace NA1;

  9. int main(void){
  10.         print("Tom");
  11.         print(12);
  12.         print(12.23);
  13. }
复制代码

论坛徽章:
0
4 [报告]
发表于 2012-02-21 15:30 |只看该作者
回复 3# DIYBYPERL


能编译通过吗?二义性。

    mian函数内没有引入任何名字空间,于是在全局空间查找,虽然全局空间中引入了NA1,但是全局空间已经是最外围了,NA1没法包含全局空间了,只能委屈委屈和全局空间合并。
于是参数列表时double的print函数有两个(NA1一个,全局空间一个),报错二义性

论坛徽章:
0
5 [报告]
发表于 2012-02-21 15:56 |只看该作者
可以的

论坛徽章:
0
6 [报告]
发表于 2012-02-21 17:38 |只看该作者
本帖最后由 x5miao 于 2012-02-21 17:41 编辑

回复 2# EasyIOCP


    我也觉得print(12)调用时有二义性错误。

论坛徽章:
0
7 [报告]
发表于 2012-02-21 19:08 |只看该作者
本帖最后由 DIYBYPERL 于 2012-02-21 19:09 编辑

终于解决了,总结如下:
        using 指示符可以一次让名字空间的所有成员都可见,就好象所有成员是在名字空间之外、在定义名字空间的位置上被声明的一样。
        using 指示符只对using 指示符所在的域从using 指示符出现起到该域结束中间部分及嵌套域起作用。
        例如以下代码,当在代码没被注释时,函数f调用Label 1的print函数;Label 1 被注释时调用Label 2 处的print;再把Label 2注释时,调用Label 8处的print,这是因为Label 4处使用的using namespace NA01语句使NA01的所有成员在NA01的空间外但在NA01的定义处可见了,同时NA01的print与Label 3处的print构成了重载函数,但NA01的print是精确匹配;再把Label 3和Label 4的注释时调用Label 9处的print,也是因为Label 5处使用的using namespace NA02语句使NA02的所有成员在NA02的空间外但在NA02的定义处可见了;再把Label 5注释时则会报重载的二义性错误,因为Label 6和Label 7的语句使OTH02和OTH02::OTH01的print函数在全局域中可见了,并与Label 10的print函数构成了三个函数的重载集合,但Label 11 和 Label 12 的都是精确匹配;再把Label 6、Label 7注释时调用Label 10处的print;再把Label 10也注释时就会报找不到函数的错。
  1. #include <iostream>
  2. using namespace std;
  3. //global
  4. namespace OTH02{
  5.         void print(int){cout<<"OTH02"<<endl;}//Label 12.
  6.         namespace OTH01{
  7.                 void print(int){cout<<"OTH02::OTH01::print"<<endl;}//Label 11.
  8.         }//OTH01
  9. }//OTH02
  10. void print(double){cout<<"::print(double)"<<endl;}//Label 10.


  11. namespace Out02{
  12.         namespace NA02{
  13.                 void print(int){cout<<"Out02::NA02::print"<<endl;}//Label 9.
  14.         }

  15.         namespace Out01{
  16.                 namespace NA01{
  17.                         void print(int){cout<<"Out02::Out01::NA01::print"<<endl;}//Label 8.
  18.                 }
  19.                 void print(double){cout<<"Out02::Out01::print"<<endl;}//Label 3.

  20.                 namespace Out{
  21.                         void print(int){cout<<"Out02::Out01::Out::print"<<endl;}//Label 2.
  22.                         namespace NA{
  23.                                 using namespace NA01; //Label 4.
  24.                                 using namespace NA02; //Label 5.
  25.                                 using namespace OTH02; //Label 6.
  26.                                 using namespace OTH02::OTH01; //Label 7.
  27.                                 void print(int){cout<<"Out02::Out01::Out::NA::print"<<endl;} //Label 1.
  28.                                 void f(){
  29.                                        
  30.                                         print(12);
  31.                                 }

  32.                                

  33.                         }//NA

  34.                 }//Out
  35.         }//Out01
  36. }//Out02


  37. int main(void){
  38.         Out02::Out01::Out::NA::f();
  39. }
复制代码

论坛徽章:
0
8 [报告]
发表于 2012-02-21 21:55 |只看该作者
本帖最后由 x5miao 于 2012-02-21 22:06 编辑

回复 7# DIYBYPERL


    你的理解不对吧。

《C++ PRIMER》里面有句话:“由using指示引起的二义性在使用处被检测到”,这说明using指示并不是简单的相当于在包含using指示和命名空间本身的作用域中重新声明一下名字那么简单。

我的理解是c++编译器在确定名字的实体的时候遵守的顺序是:
(1)首先进行名字查找,此时的名字都是没有类型信息,所有重载的函数此时共享一个名字,一旦查找到名字就停止查找。
(2)确定是否有重复定义或者矛盾声明等错误,如int i;double i;这样的矛盾声明
(3)确定名字对应的实体,对于重载函数而言就是函数匹配的过程。

using声明和using指示对名字查找过程和重载函数匹配过程的影响是不一样的

不知道C++标准对using关键字的作用是怎么叙述的

论坛徽章:
0
9 [报告]
发表于 2012-02-21 22:50 |只看该作者
13 Overloading [over]
1 When two or more different declarations are specified for a single name in the same scope, that name is
said to be overloaded. By extension, two declarations in the same scope that declare the same name but
with different types are called overloaded declarations. Only function declarations can be overloaded;
object and type declarations cannot be overloaded.

3.3.7 Name hiding
4 During the lookup of a name qualified by a namespace name, declarations that would otherwise be made
visible by a using-directive can be hidden by declarations with the same name in the namespace containing
the using-directive; see (3.4.3.2).
5 If a name is in scope and is not hidden it is said to be visible.


论坛徽章:
0
10 [报告]
发表于 2012-02-22 08:25 |只看该作者
x5miao 发表于 2012-02-21 21:55
回复 7# DIYBYPERL


我总结的并没有这个意思啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP