c++使用声明和函数重载
c++ using declaration and function overload
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 X
和using 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);
}
在这里,A
和B
成员都将在名称查找期间被考虑,并且您将得到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 directive
和using 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;
相同的结果。
- 为什么使用SFINAE而不是函数重载
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- c++:可变模板和函数重载
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- 解决模板成员函数重载
- 为什么不允许成员函数和非成员函数之间的函数重载?
- 推断模板化函数中的函数重载
- C++复制函数重载导致"must be a nonstatic member function"错误
- 为什么 std::sort 找不到合适的(静态成员)函数重载?
- 可变参数泛型 lambda 和函数重载
- C++中的函数重载和继承
- 当有右值构造函数可用时,为什么从右值调用类引用构造函数重载?
- C/C++ 可变参数宏函数重载
- 将基类的成员函数重载到其他派生类C++
- C++ 函数重载匹配
- C++函数重载,具体步骤是什么
- C++:使用 param pack 显式调用函数重载
- 隐式生成的函数重载用于右值参数?
- 使用函数重载输入运算符
- 运算符重载函数上的函数重载