【问题标题】:Trailing underscores for member variables in C++C ++中成员变量的尾随下划线
【发布时间】:2011-04-08 17:09:45
【问题描述】:

我见过人们在类中为成员变量使用尾随下划线,例如在著名的 C++ FAQ Lite 中。

我认为它的目的不是将变量标记为成员,这就是“m_”的用途。它的实际目的是使访问器方法可以像字段一样命名,如下所示:

class Foo {
public:
    bar the_bar() { return the_bar_; }
private:
    bar the_bar_;
}

让访问器省略“get_”部分在 STL 和 boost 中很常见,我正在尝试开发一种尽可能接近这些的编码风格,但我无法真正看到它们使用下划线技巧。我无法在 STL 或 boost 中找到只会返回私有变量的访问器。

我有几个问题希望你能回答:

  1. 这个约定从何而来?短暂聊天?目标-C?微软?我想知道。
  2. 我应该对所有私有成员使用尾随下划线,还是仅作为一种解决方法,以防我想将函数命名为变量?
  3. 您能否指点我使用 STL 或 boost 代码来演示成员变量的尾随下划线?
  4. 有人知道 Stroustrup 对此问题的看法吗?
  5. 您能否指出我对该问题的进一步讨论?

【问题讨论】:

  • @Nick D:这怎么可能是重复的,你读了吗?它提出了一个完全不相关的问题,即前导 (!) 下划线在 C++ 中是否合法。
  • @chubsdad:我读过,但他并没有真正提到尾随下划线或访问器。他只是说他不喜欢有很多 get/set 函数的类。
  • 对于第 3 点,在 boost/asio/ssl/stream.hpp 中有一个成员 next_layer_ 的示例
  • 我还发现了一些在标准中以尾随下划线命名的“仅展示”数据成员:)

标签: c++ naming-conventions member


【解决方案1】:

在 C++ 中,

  1. 以下划线开头,后跟大写字符的标识符
  2. 在任意位置有两个连续下划线的标识符
  3. 全局命名空间中以下划线开头的标识符

保留给实现。 (有关此的更多信息可以在here 找到。)许多人没有尝试记住这些规则,而是根本不使用以下划线开头的标识符。这就是发明尾随下划线的原因。

但是,C++ 本身已经过时了,并且建立在 40 年的 C 基础之上(两者都没有一家公司支持它们),并且有一个标准库在几十年内“成长”,而不是被引入单一的创造行为。这使得存在许多不同的命名约定。私有(或仅用于私有数据)的尾随下划线只是一个,许多人使用其他下划线(其中不少人认为,如果您需要下划线来告诉私有成员与局部变量,那么您的代码不够清晰)。

至于 getter/setter - 他们是可憎的,是我讨厌的 "quasi classes" 的明确标志。

【讨论】:

  • 我和你在一起,我尽可能避免使用 getter/setter。但有时,它们实际上很有用——尤其是在使用 GOF 设计模式时。一个简单的例子:考虑一个拥有和初始化对象的类(如游戏引擎中的图形子系统)并允许其他类访问它们。我会使用访问器方法,因为声明变量 public 将允许读/写访问,而我只想允许读访问。在使用访问器时,我还可以返回一个 const 引用以确保 const 的正确性。
【解决方案2】:

据我所知,为成员推送尾随下划线代码样式的不是微软。

我读到 Stroustrup 是支持尾随下划线的。

【讨论】:

  • “它一次给我所有信息” - 直到有人更改类型并忘记更新伪匈牙利标签。然后它们不再有用并变得非常有害。
  • en.wikipedia.org/wiki/Hungarian_notation: 来自 Bjarne 的引用:“不,我不推荐‘匈牙利语’。我认为‘匈牙利语’(在变量名中嵌入类型的缩写版本)是一种可以在无类型语言中很有用,但完全不适合支持泛型编程和面向对象编程的语言——两者都强调基于类型和参数(语言或运行时支持已知)选择操作。在这种情况下,“将对象的类型构建到名称中”只会使抽象复杂化并最小化”
  • 匈牙利表示法的最大问题是您必须更改类型,无论该变量所在的位置如何,您都必须更新源代码,而这在大多数编辑器中很容易,它会分散审阅者的注意力查看差异时。
  • @Stephane:那句话不是关于下划线的,是吗?
  • 减 1 表示您对(不必要的、有风险的)匈牙利语的偏离主题的个人偏好,其写作方式错误地暗示 Stroustrup 喜欢它。
【解决方案3】:

我已阅读C++ 编程语言,并且 Stroustrup 没有使用任何类型的命名成员的约定。他从来不需要;没有一个简单的访问器/修改器,他有一种创建非常精细的面向对象设计的方法,因此不需要同名的方法。只要他需要简单的数据结构,他就会使用带有公共成员的结构。他的方法似乎总是操作。我还在某处读到,他不鼓励使用仅相差一个字符的名称。

【讨论】:

  • std::vector::size() 怎么样?我想它可能包含一个size_ 成员。
  • “只要他需要简单的数据结构,他就会使用带有公共成员的结构。”那个危险的叛徒! (+1)
  • @claymation,有时可能需要计算大小(例如,不存储元素计数的快速链表),但插入很频繁。对于一个从不需要的值来说,读增量存储可能开销太大。
【解决方案4】:

作为喜欢可搜索性的维护开发人员,我倾向于m_,因为它更易于搜索。当你和我一样维护大型项目时(不要问),你有时会想:“嗯,谁改变了状态?”。快速搜索m_ 可以给出提示。

我也知道使用l_ 表示局部变量,但当前项目不使用它,所以这些天我很“干净”。

我不喜欢匈牙利符号。 C++ 有一个强大的类型系统,我用它来代替。

【讨论】:

  • Fwiw,除了m_,在使用 CRTP 时,我在静态类成员/方法前加上 s_,在派生实现前加上 d_。我从来没有尝试过使用l_/p_... 来表示本地人与参数,有点希望我不要这样做,因为这需要做很多工作才能改变。 :P
【解决方案5】:

我猜想 utopia 会使用前导下划线 - 这在 Java 和 C# 中对于成员来说很常见。

但是,对于 C,前导下划线不是一个好主意,因此我猜 C++ FAQ Lite 建议使用尾随下划线:

所有以 下划线和大写字母 字母或另一个下划线是 始终保留用于任何用途。

所有以 下划线始终保留使用 作为两者中具有文件范围的标识符 普通名称空间和标记名称空间。


(ISO C99 规范,第 7.1.3 节)

【讨论】:

    【解决方案6】:

    我个人是这个指南的忠实粉丝:http://geosoft.no/development/cppstyle.html

    它包括省略 m_ 前缀,使用下划线后缀来指示私有成员变量,并放弃使用下划线而不是空格的可怕、烦人的打字习惯,以及其他更详细和具体的建议,例如命名布尔值适当地(isDone 而不是 done)并使用 getVariable() 而不是 variable() 仅举几例。

    【讨论】:

    • 嗯,这些东西大部分只是个人审美偏好,直到this great Coding Standard 将所有这些都包含为: 0. 不要为小事出汗。 (或者:知道什么不应该标准化。)......只要保持一致。
    • 我也不喜欢使用[get|compute]Data(),因为像use( texture.data() ); 这样的代码在IMVHO 上的阅读效果要好得多,并且不会因为他不应该关心的细节(例如数据是否是缓存或需要计算。
    • 我认为is_done 的阅读效果比isDone 好得多。 _ 更像是一个空间,而不是完全没有空间。
    • 有趣的是,这个风格指南推荐了一些在 STL 中没有用到的东西。例如,驼峰式类型名称。
    【解决方案7】:

    只代表我自己... 我总是对私有数据成员使用尾随下划线,无论它们是否具有访问器功能。我不使用 m_ 主要是因为它会妨碍我在脑海中拼写变量的名称。

    【讨论】:

    • 同意并走得更远——我使用带有任何私有符号的尾随下划线(在 C++ 和 Java 中),并发现“m_”是可憎的(匈牙利符号的剩余部分)。下划线允许在私有和非私有上下文中使用“相同”的名称,其中该名称是最合适的。
    猜你喜欢
    • 2014-04-14
    • 2021-05-14
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多