c ++使用声明和函数重载

时间:2015-08-28 07:49:26

标签: c++

  1 #include <iostream>
  2 
  3 namespace primerlib {
  4     void compute() { std::cout << "primerlib::print()" << std:: endl; }
  5     void compute(const void *p) { std::cout << "primerlib::print(const void *p)" << std:: endl; }
  6 }
  7 
  8 //using primerlib::compute;
  9 //using namespace primerlib;
 10 void compute(int a) { std::cout << "::compute(int)" << std:: endl; }
 11 void compute(double d, double dd=3.4) { std::cout << "primerlib::compute(d, d)" << std:: endl; }
 12 void compute(char* p, char* p1 = 0) { std::cout << "primerlib::compute(char*, char*)" << std:: endl; }
 13 
 14 int main(void)
 15 {
 16     using primerlib::compute;
 17     //using namespace primerlib;
 18     compute(0);
 19     return 0;
 20 }

输出:

primerlib::print(const void *p)

我的问题是为什么它没有调用全局计算(int)?如果我在第17行使用using指令,它将调用compute(int)。非常感谢您的帮助。

4 个答案:

答案 0 :(得分:4)

这是因为using namespace Xusing X::Y的工作方式不同。使用using namespace X时,在名称查找期间会考虑该命名空间中的所有内容。请考虑以下示例:

namespace A
{
    void foo(int){}
}

namespace B
{
    void foo(int){}
}

using namespace A;
using namespace B;

int main()
{
    foo(1);
}

此处,在名称查找期间将考虑AB成员,并且您将遇到call of overloaded foo(int) is ambiguous错误,因为编译器无法确定两个函数中的哪一个使用,因为它们是相同的。 using X::Y语法旨在解决此问题。当您使用它时,您告诉编译器仅使用Y命名空间中的X,而不考虑其他任何内容。我们将其添加到上面的示例中:

namespace A
{
    void foo(int){}
}

namespace B
{
    void foo(int){}
}

using namespace A;
using namespace B;


int main()
{
    using A::foo;  
    foo(1);
}

这里我们告诉编译器使用foo命名空间中找到的A实例,并忽略范围内的任何其他foo。因此,在您的示例中,您告诉编译器仅使用primerlib::compute,如果要从全局范围访问函数,则必须使用::compute(),并调用compute(int) }。

答案 1 :(得分:1)

  

使用primerlib :: compute;

这是using声明。当您使用它时,就好像在声明的位置声明了一个名称。您可以通过添加foo(或使用全局范围using ::foo;调用全局::foo(0);来恢复全局::compute(int),您将在输出中看到foo

在您的示例编译器中未找到全局using declaration声明的事实是因为这是名称查找的工作方式 - 它会在找到名称后搜索封闭的范围和stope。

有关使用声明的更多参考,请参阅:http://en.cppreference.com/w/cpp/language/namespace#Using-declarations

[编辑]

我误解了你的问题,在第17行你有'使用指令',它的行为与 foreach ($array as $key => $value) { if ((isset($array[$key+1)) && ($array[$key]['released'] === false && ($array[$key+1]['released'] === false)){ unset($array[$key]); } } return $array; 不同,它没有在最近的封闭声明区域(在你的情况下是它的主函数)中引入名称,但添加了名称到最近的封闭命名空间 - 在这个演员表中它是全局命名空间。有关更多参考:http://en.cppreference.com/w/cpp/language/namespace#Using-directives

  

只允许在命名空间范围和块范围内使用using指令。从使用指令之后的任何名称的非限定名称查找的角度来看,直到它出现的作用域的结尾, 来自namespace-name的每个名称都是可见的,就像它在最近的封闭命名空间 ,其中包含using-directive和namespace-name。

     

使用-directive不会向显示的声明区域添加任何名称 (与using-declaration不同),因此不会阻止相同的名称声明。

答案 2 :(得分:0)

使用实际的using声明,你说compute是一个只引用namespace primerlib中定义的函数的名称:实际上如果你试图调用接受double的compute函数,你会得到一个没有匹配函数的错误。 使用注释使用声明,您可以为所有计算功能提供相同的重要性&#34;:引用全局计算功能,您必须使用&#34; ::&#34;命名空间解析指令,要引用引号的命名空间,你必须使用&#34; primerlib ::&#34;命名空间解析指令。

答案 3 :(得分:0)

在这种情况下,

using directiveusing declaration会有所不同。

7.3.4 $ 2使用指令[namespace.udir] :(由我粗体)

  

using-directive指定指定名称空间中的名称   可以在using指令出现的范围内使用   使用指令。在非限定名称查找(3.4.1)期间,名称   看起来好像是在最近的封闭命名空间中声明的   它包含using-directive和指定的命名空间。 [   注意:在此上下文中,“包含”表示“直接包含或   间接地”。 - 后注]

在这种情况下,最近的封闭命名空间是全局namaspace,命名空间primerlib的函数与其他全局函数出现在同一命名空间中,因此在调用重载分辨率::compute(int)之后。

7.3.3 $ 1使用声明[namespace.udecl]:

  

using声明在声明区域中引入了一个名称   其中出现了使用声明。

命名空间primerlib的函数将被引入main函数范围,它们将在具有高优先级的名称查找阶段被选中,然后名称查找将停止。全局函数不会考虑重载分辨率,因此调用了primerlib::compute(const void *p)

顺便说一句:如果您将using primerlib::compute;移出main功能,您将获得与在using namespace primerlib;函数中使用main相同的结果。

LIVE