【问题标题】:C++ Should I fully qualified my variable type?C++ 我应该完全限定我的变量类型吗?
【发布时间】:2012-10-05 06:34:04
【问题描述】:

我正在尝试编写适合最多 80 列的代码行。因此,我想知道完全限定我的变量类型是否真的是强制性的?假设如下实现:

//Baz.h
namespace loggingapi {
namespace attributes {
    class Baz {};
}} // namespaces

// Bar.h
namespace loggingapi {
    namespace attributes {
        class Baz; // forward declare Baz.
    }

    class Biz {
        int f(Baz* b);
    };
} // namespaces

要声明我的函数参数类型,有多种方法?

  • a) int f(Baz* b);
  • b) 或int f(attributes::Baz* b);
  • c) 或int f(loggingapi::attributes::Baz* b);
  • d) 或int f(::loggingapi::attributes::Baz* b);

在上面的列表中,哪些定义对编译器来说更清晰/不明确?

注意:您必须假定命名空间/参数/类/函数名称在以下实现中不能缩短。

【问题讨论】:

  • 你不应该为编译器编写代码,而应该让人们阅读
  • @iammlind:我删除了多余的 (d)。很高兴尚未在任何答案中提及。
  • 或者 (e) 跳过古老的 80 列规则。一个 24 英寸的显示器可以轻松容纳 250 列。
  • @BoPersson:这是 for 80 列规则的论据。三路合并可以将基本、远程和本地版本与下面的输出并排保存……但前提是您将代码保持在
  • @BoPersson:就个人而言,我不希望在监视器连接中拆分并排差异。排长队意味着我的眼睛需要进行大量的左右扫描。保持较短的行和较短的标识符不那么累,有助于理解并减少出错的可能性。这绝对不是混淆代码。

标签: c++ namespaces c++98


【解决方案1】:

变体 e ?

namespace loggingapi {
    namespace attributes {
        class Baz; // forward declare Baz.
    }

    class Biz {
        typedef attributes::Baz Baz;
        // C++ 11 alternative
        // using Baz = attributes::Baz;

        int f(Baz* b);
    }
} // namespaces

不要忘记别名可以为您做什么......

【讨论】:

  • 也许别名是要走的路?它将允许完全限定类型并创建别名,然后改用别名。在公共 API 或继承目的的标头中使用别名有什么缺点吗?
  • @DavidAndreoletti:嗯,这意味着再创建一个符号,它可能会在您使用别名的上下文中发生冲突。在命名空间中,这是一个无限上下文,它可以根据需要经常重新打开,这可能是一个问题;但是在一个封闭的班级(如这里)中,则没有惩罚。
【解决方案2】:

我会选择 b) 变体。我的理由如下:

  • 我们假设开发人员现在知道他在哪个命名空间中。因此,在查看class Biz 时,开发人员应该知道该类位于loggingapi 命名空间中,因此无需显式声明它。
  • 另一方面,a) 变体不够清晰,因为我们应该指出BazBiz 实际上位于不同的命名空间中。此外,它不会编译,因为编译器会在 loggingapi 命名空间中查找 Baz,但它不存在。

【讨论】:

    【解决方案3】:

    您应该选择 (b)。它更灵活。如果您决定移动或(喘气)剪切和粘贴 f 并且它与新命名空间或项目相关的类型,那么使用 (b) 可确保声明的结构保持内部一致。

    您可以选择添加、删除或重命名外部包装命名空间,而不会影响封闭的代码。

    【讨论】:

      【解决方案4】:

      在 h 文件中最好使用完全限定名称,以防止客户端代码中可能出现的歧义。在 .cpp 文件中,您可以使用短符号,如果您愿意,只要没有名称冲突即可。

      【讨论】:

        【解决方案5】:

        如果编译器有一些歧义,它肯定会报错。

        我认为问题应该是关于人类读者的,这是相当主观的。
        命名约定取决于

        1. 预先确定的编码风格
        2. 在哪里声明函数f()

        没有明确的选择。我希望,如果两个实体都属于同一个namespace,那么我将至少从名称中省略那部分:

        namespace loggingapi {
            namespace attributes {
                class Baz; // forward declare Baz.
            }
        
            class Biz {
                int f(attribute::Baz* b);
            };      // ^^^^^^^^^^^^^
        }
        

        【讨论】:

          猜你喜欢
          • 2014-10-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-30
          • 1970-01-01
          • 2016-10-05
          • 2011-10-15
          • 2018-12-10
          相关资源
          最近更新 更多