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

c++ using declaration and function overload

本文关键字:函数 重载 声明 c++      更新时间:2023-10-16
  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)

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

这是因为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语法就是为了解决这个问题。当您使用它时,告诉编译器只使用在X名称空间中找到的Y,而不考虑其他任何内容。让我们将它添加到上面的示例中:

namespace A
{
    void foo(int){}
}
namespace B
{
    void foo(int){}
}
using namespace A;
using namespace B;

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

这里我们告诉编译器使用在A命名空间中找到的foo实例,并忽略范围内的任何其他foo。所以,在你的例子中,你告诉编译器只使用primerlib::compute,如果你想从全局作用域访问函数,你必须使用::compute(),并调用compute(int)

使用primerlib

::计算;

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

在您的示例编译器中没有找到全局foo声明的事实,是因为这就是名称查找的工作方式-它搜索封闭范围并在找到名称后停止。

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

[编辑]

我误解了你的问题,在第17行你有"使用指令",它的行为与using declaration不同,它没有在最近的封闭声明性区域(在你的情况下它的主要功能)中引入名称,而是将名称添加到最近的封闭命名空间-在这个类型中它是全局命名空间。更多参考:http://en.cppreference.com/w/cpp/language/namespace#Using-directives:

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

Using-directive不会将任何名称添加到它出现的声明区域(与using- statement不同),因此不会阻止声明相同的名称。

在实际的using声明中,您说compute是一个仅引用命名空间primerlib中定义的函数的名称:实际上,如果您尝试调用接受双精度类型的compute函数,则会得到没有匹配函数的错误。使用注释的using声明,你给所有的计算函数"相同的重要性":要引用全局的,你必须使用"::"命名空间解析指令,要引用primer的命名空间,你必须使用"primerlib::"命名空间解析指令。

using directiveusing declaration在这种情况下的行为不同。

7.3.4$2使用指令[namespace。(粗体by me)

using指令指定命名空间中的名字是否可以在using指令之后出现的范围内使用使用指示。在非限定名称查找(3.4.1)期间看起来好像它们是在最近的封闭命名空间中声明的。它同时包含using指令和指定的命名空间。[注意:在这种情况下,"contains"的意思是"直接包含或"间接地"。-end note]

在本例中,最近的封闭命名空间是全局命名空间,命名空间primerlib的函数与其他全局函数出现在同一个命名空间中,因此重载解析后调用::compute(int)

7.3.3$1 using声明[namspace .udecl]:

using声明将名称引入到中的声明区域中

将命名空间primerlib的函数引入main函数作用域,并在名称查找阶段以高优先级选择它们,然后停止名称查找。全局函数不考虑重载解析,所以调用primerlib::compute(const void *p)

BTW:如果您将using primerlib::compute;移出main函数,您将获得与在main函数中使用using namespace primerlib;相同的结果。

生活