在 C++ 中使用 std 命名空间的完全限定名称
Using fully qualified name for std namespace in C++
如果 C++ 中的名称不是完全限定的,例如std::cout
,它可能会导致意外错误,例如 https://en.cppreference.com/w/cpp/language/qualified_lookup 中提到的错误。但是使用 ::std
命名空间的完全限定名称 e.q。 ::std::cout
,非常罕见,正如我所注意到的。
为什么不使用 ::std
命名空间的完全限定名称有什么原因吗?
以及如何为自己创建的命名空间使用完全限定名称?这是个好主意吗?
你是完全正确的,从某种意义上说,如果有一个命名空间 yyyy
和 class yyyy
两者都可见,那么 yyyy::xxx
可能是不明确的相同的范围。在这种情况下,只有完全限定 ::yyyy::xxx
才能解决歧义。您的 link 示例非常清楚:
// from cppreference.com
#include <iostream>
int main() {
struct std{};
std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
::std::cout << "ok\n"; // OK: ::std finds the namespace std
}
但在实践中,很难在顶层创建冲突的 std
,因为标准库中的大多数包含都会使其失败:
#include <iostream>
struct std { // OUCH: error: ‘struct std’ redeclared as different kind of symbol
int hello;
};
这意味着要创建冲突,您需要定义本地 classes 或在另一个名称空间中引入 using
子句。另外,没有人会(敢)叫一个classstd
。
最后,在实践中,::yyyy::xxx
阅读起来不太方便。所有这些都解释了为什么您不会经常找到它。
补充说明
问题不在于众所周知的 std
,而在于您自己的名称空间和第三方库。在这种情况下,namespace alias 将是 :::yyyy
更好的替代方法来消除歧义:
namespace foo {
void printf() { }
}
int main() {
foo::printf(); // ok, namespace is chose because no ambiguity
struct foo {/*...*/ }; // creates ambiguity
//foo::printf(); // error because struct foo is chosen by name lookup
::foo::printf(); // ok, but not if you decide to move the code to be nested in another namespace
namespace mylib = foo ; // or ::foo (see discussion below)
mylib::printf(); // full flexibility :-)
}
它的优点是灵活性更高。例如,假设您要移动代码以将其嵌套在封闭的名称空间中。使用命名空间别名,您的代码可以继续按原样工作(在最坏的情况下,只需对别名定义进行微小调整)。使用全局范围解析,您必须更改将使用全局命名空间 ::foo
的所有语句。
为了保持大代码或更好的可读性或名称冲突,C++ 提供了命名空间“声明区域”。
名称空间定义只能出现在全局范围内,或嵌套在另一个名称空间中。
#Sample Code
#include <iostream>
int main()
{
struct std{};
std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
::std::cout << "ok\n"; // OK: ::std finds the namespace std
}
在上面的代码中,编译器正在 struct std 中寻找 cout,但是在下一行中使用 ::std::cout 它在全局定义的标准 class.
中寻找 cout
解决方案:
#include <iostream>
//using namespace std; // using keyword allows you to import an entire namespace at once.
namespace test
{
void cout(std::string str)
{
::std::cout<<str;
}
}
int main()
{
cout("Hello");//'cout' was not declared in this scope
::test::cout("Helloo ") ;
::std::cout<<"it is also ok\n";
}
或者这样使用,只是为了更好的可读性
##
using namespace test;
int main()
{
cout("Hello");//'cout' was not declared in this scope
cout("Helloo ") ;
::std::cout<<"it is also ok\n";
}
如果 C++ 中的名称不是完全限定的,例如std::cout
,它可能会导致意外错误,例如 https://en.cppreference.com/w/cpp/language/qualified_lookup 中提到的错误。但是使用 ::std
命名空间的完全限定名称 e.q。 ::std::cout
,非常罕见,正如我所注意到的。
为什么不使用 ::std
命名空间的完全限定名称有什么原因吗?
以及如何为自己创建的命名空间使用完全限定名称?这是个好主意吗?
你是完全正确的,从某种意义上说,如果有一个命名空间 yyyy
和 class yyyy
两者都可见,那么 yyyy::xxx
可能是不明确的相同的范围。在这种情况下,只有完全限定 ::yyyy::xxx
才能解决歧义。您的 link 示例非常清楚:
// from cppreference.com
#include <iostream>
int main() {
struct std{};
std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
::std::cout << "ok\n"; // OK: ::std finds the namespace std
}
但在实践中,很难在顶层创建冲突的 std
,因为标准库中的大多数包含都会使其失败:
#include <iostream>
struct std { // OUCH: error: ‘struct std’ redeclared as different kind of symbol
int hello;
};
这意味着要创建冲突,您需要定义本地 classes 或在另一个名称空间中引入 using
子句。另外,没有人会(敢)叫一个classstd
。
最后,在实践中,::yyyy::xxx
阅读起来不太方便。所有这些都解释了为什么您不会经常找到它。
补充说明
问题不在于众所周知的 std
,而在于您自己的名称空间和第三方库。在这种情况下,namespace alias 将是 :::yyyy
更好的替代方法来消除歧义:
namespace foo {
void printf() { }
}
int main() {
foo::printf(); // ok, namespace is chose because no ambiguity
struct foo {/*...*/ }; // creates ambiguity
//foo::printf(); // error because struct foo is chosen by name lookup
::foo::printf(); // ok, but not if you decide to move the code to be nested in another namespace
namespace mylib = foo ; // or ::foo (see discussion below)
mylib::printf(); // full flexibility :-)
}
它的优点是灵活性更高。例如,假设您要移动代码以将其嵌套在封闭的名称空间中。使用命名空间别名,您的代码可以继续按原样工作(在最坏的情况下,只需对别名定义进行微小调整)。使用全局范围解析,您必须更改将使用全局命名空间 ::foo
的所有语句。
为了保持大代码或更好的可读性或名称冲突,C++ 提供了命名空间“声明区域”。 名称空间定义只能出现在全局范围内,或嵌套在另一个名称空间中。
#Sample Code
#include <iostream>
int main()
{
struct std{};
std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
::std::cout << "ok\n"; // OK: ::std finds the namespace std
}
在上面的代码中,编译器正在 struct std 中寻找 cout,但是在下一行中使用 ::std::cout 它在全局定义的标准 class.
中寻找 cout解决方案:
#include <iostream>
//using namespace std; // using keyword allows you to import an entire namespace at once.
namespace test
{
void cout(std::string str)
{
::std::cout<<str;
}
}
int main()
{
cout("Hello");//'cout' was not declared in this scope
::test::cout("Helloo ") ;
::std::cout<<"it is also ok\n";
}
或者这样使用,只是为了更好的可读性
##
using namespace test;
int main()
{
cout("Hello");//'cout' was not declared in this scope
cout("Helloo ") ;
::std::cout<<"it is also ok\n";
}