【问题标题】:Namespace information compromises the readability in C++命名空间信息损害了 C++ 中的可读性
【发布时间】:2020-01-15 11:36:47
【问题描述】:

我是C++ 的新手,在C 有背景。我很难采用的一件事是经常使用范围运算符,例如std:: 好吧,我会通过将using namespace std 放在我的源代码开头来避免使用它,但是很多人不使用这种方法,因为他们认为这可能会在将来对他们不利。

另外,visual-studio 还显示范围运算符中的错误/警告消息,例如

cannot convert from 'std::vector<int,std::allocator<_Ty>> *' to 'std::shared_ptr<std::vector<int,std::allocator<_Ty>>>'

虽然上面的消息很冗长,但读起来很痛苦(?)。我认为如果是这种形式,阅读起来会很简单

cannot convert from 'vector<int,allocator<_Ty>> *' to 'shared_ptr<vector<int,allocator<_Ty>>>'

1) 为什么每个人都在使用std::,甚至是coutcinendl?为什么会有人将这些标签用于其他目的?

2) 他们是 Visual Studio 中的一种解决方法,不向我显示带有前缀 std:: 的错误/消息/语法高亮吗?

【问题讨论】:

  • 1) "虽然上面的信息很冗长,但读起来很痛苦(?)。" 如何/为什么? 2) Why is “using namespace std;” considered bad practice? 3) “他们在 Visual Studio 中是一种解决方法,不向我显示带有前缀 std:: 的错误/消息/语法高亮吗?”用户定义的类型/函数呢?在命名空间中定义?他们不应该有那个限定词吗?那么,如果不显示命名空间,您将如何区分这些名称?
  • 只需将命名空间视为名称的一部分。
  • 另外,问问自己如果你的代码中有一些东西,在任何命名空间之外,没有std:: 的错误消息将意味着什么,命名为vector

标签: c++ visual-studio namespaces readability name-lookup


【解决方案1】:

尽管如 cmets 中所指出的,using namespace std; 之类的代码是 considered bad practice,但您可以通过指定 individual 范围元素来避免在 std::cout 之类的代码中重复使用命名空间前缀在using 语句中。

类似这样的:

using std::cout;  //
using std::cin;   // You can, from then on, just use 'cout', 'cin' and 'endl'
using std::endl;  //

对于 非常 常见的元素,如上面代码中列出的元素,您可以将相关的 using 行放在头文件中 - 通常是用于构建您的“全局”头文件预编译头文件。

【讨论】:

    【解决方案2】:

    对于初学者来说,限定名称和非限定名称的名称查找有所不同。

    以下面的程序为例。

    #include <iostream>
    
    class A
    {
    private:    
        int x = 10;
    
    public:
        operator int() const { return x; }
        friend void f( const A & )
        {
            std::cout << "f( const A & )\n";
        }
    };
    
    void f( int )
    {
        std::cout << "f( int )\n";
    }
    
    int main() 
    {
        const A a;
    
        f( a );
    
        ::f( a );
    
        return 0;
    }
    

    程序输出是

    f( const A & )
    f( int )
    

    第二次使用 using 指令可能会导致名称冲突或由于重载解析而选择错误的函数。

    除此之外,代码的可读性可能会降低,因为例如,读者将不知道 endlstd::endl 还是在名称查找中包含的某个命名空间中定义的用户定义函数,因为许多 using 指令。

    在某些情况下,您需要使用显式或隐式 using 指令。

    例如,如果您想使用来自命名空间std::placeholders 的声明,或者当您想声明一个内联命名空间时。但这些指令的范围通常非常有限。另一个例子是使用 using 声明。但是再次尝试使他们的范围尽可能小。

    【讨论】:

      【解决方案3】:

      在有限范围内,例如在函数内,使用using namespace std 或任何其他using 是合乎逻辑的。

      如果您可以免费避免重复命名空间名称,那么它会很乏味。我已经看到很多代码都被std:: 感染了,尤其是在使用 std::forward、std::move、std::function、std::thread 等方面。

      using 这样的C++ 关键字是有原因的;无条件地说“使用命名空间标准是不好的”是错误的。

      【讨论】:

      • 意见(基于个人经验)不同,因此在这里称您的异议为“错误”具有误导性。试图说服人们你持有的观点(欢迎你)实际上是一个事实(当它不是一个事实时)是肮脏的。 (这是我自己在“空格与制表符”辩论中可能犯的行为是无关紧要的!;)。
      • 我不是要说服任何人。
      【解决方案4】:

      要回答你的2),我相信答案是“不,没有办法改变 VS 写出错误消息的方式来过滤所有std::”。

      好消息是这些错误消息过去要糟糕得多。您会收到给定模板上所有 N 个变体的错误消息,然后必须从噪声海洋中解析出微小的信号规范。不好玩。如果您使用像 std::vector&lt;std::vector&lt;std::string&gt; &gt; &gt; 这样的嵌套模板,天堂会帮助您。

      因此,虽然模板错误消息可能仍然有点冗长,但所提供的信息是实际信息,而不是垃圾邮件垃圾邮件垃圾邮件和没有鸡蛋的垃圾邮件。

      哦,&gt;&gt; 过去总是解析为流运算符,因此您必须在 &gt;s 之间添加空格以用于嵌套模板。 上山,双向!!!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-18
        • 2018-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多