在C ++中使用std名称空间的完全限定名称

问题描述 投票:7回答:2

如果C ++中的名称不完全合格,例如std::cout,它可能导致无意的错误,例如在https://en.cppreference.com/w/cpp/language/qualified_lookup提到的。但是使用::std命名空间的完全限定名称,e.q。 ::std::cout,非常罕见,正如我所注意到的那样。

是否有任何理由不使用::std命名空间的完全限定名称?

那么为自己创建的命名空间使用完全限定名称呢?这是好主意吗?

c++ namespaces naming name-lookup scope-resolution
2个回答
10
投票

你是完全正确的,在某种意义上说,如果有一个命名空间yyyy::xxx和一个类yyyy,它们在同一范围内都可见,那么yyyy可能是模棱两可的。在这种情况下,只有完整的资格::yyyy::xxx可以解决模糊性。您的链接示例非常清楚:

// 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;  
}; 

这意味着要创建冲突,您需要定义本地类或在另一个命名空间中引入using子句。此外,没有人会(敢)打电话给std

最后,在实践中,::yyyy::xxx不太方便阅读。这一切都解释了为什么你不经常发现它。

Additional remark

问题不在于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的所有语句。


0
投票

为了维护大代码或更好的可读性或名称冲突,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时,它会在全局定义的std类中查找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";
}
© www.soinside.com 2019 - 2024. All rights reserved.