你如何将常见的C++命名约定与库的命名约定协调一致?

45
大多数C++命名惯例规定使用驼峰式标识符:camelCaseIdentifiers:类以大写字母开头的名称(PersonBooking),字段和变量以小写字母开头的名称(getPrice()isValid()largestValue)。这些建议与C++库的命名惯例完全不同,后者涉及类的小写名称(stringsetmapfstream),方法和字段使用用下划线连接的名称find_first_oflower_boundreverse_iteratorfirst_type)。更加复杂的是操作系统和C库函数,它们在C和Unix中采用压缩的小写名称,在Windows中以大写字母开头的函数名。
因此,我的代码很混乱,因为有些标识符使用C++库、C或操作系统的命名约定,而其他标识符使用规定的C++约定。编写包装库功能的类或方法很痛苦,因为最终会得到不同风格的名称来表示相似的内容。
那么,如何调和这些不同的命名约定呢?
10个回答

22

Diomidis,我能够理解你的痛苦,多年来我花费了大量时间在不同方案之间切换,试图找到适用于使用的不同库/框架的方案(如MFC和/或STL/Boost)。当仅使用一个框架(如STL)时,可以尝试复制其使用的命名约定,但是当引入不同的框架时,它很容易崩溃。

最终,我采用了一种单一的风格来编写所有新代码(基于Google C++风格指南),并在适当时对旧代码进行重构以使用此风格。你无法轻易地调和不同的命名约定,因此不要浪费时间去尝试。强制执行一个团队/部门/公司的方案,并坚持不懈-但不要纠结于使用混合方案时代码看起来有多么“丑陋”。

在我的个人意见中,Google C++指南相当不错-还要进行一些小修改。您可以在这里查看指南:

https://google.github.io/styleguide/cppguide.html#Naming


3
我正在考虑使用类似于谷歌指南的东西,但它们与STL不太搭配,这就是我问问题的原因。我想我被Java的绝对顺序宠坏了。 - Diomidis Spinellis
如果我足够幸运能够开发“纯”STL,那就不是问题了。我曾经使用多种风格,具体取决于目标框架 - 直到我开始将STL / boost与MFC混合使用时才出现问题! Google风格和我见过的任何风格一样好,尽管我稍微调整了一下。 - Rob
1
不要重命名旧代码,除非你想全部更改它 - 这会影响差异/合并,并可能会造成损失。 - gbjbaanb
当我看到他们的建议不要使用异常时,我开始怀疑他们的建议,我想:“他们在想什么,真的吗?” - user90843

20

一种方法是采用C++的naming_convention,这是现在大多数文献中代码示例所做的。

我逐渐看到这些惯例移植到生产代码中,但仍然存在许多地方支配着MFC的命名惯例。

与旧标准对抗的其他样式差异包括使用尾随下划线而不是m_来表示成员。


1
C++的命名约定将所有标识符(类和字段名称)都写成小写。你能指出推荐使用这种风格的C++样式指南吗?《C++编程规范》和《C++风格之元素》这两本书并没有提到。 - Diomidis Spinellis
我不知道有这样的文档,我从STL(显然是标准库的一部分)中推导出C++命名约定。 - Motti
3
我同意Motti的观点:虽然我更喜欢驼峰命名法,但STL使用下划线命名法,因此可以被认为是C++的“默认”风格...但是Win32 API/.NET是帕斯卡命名法,而C API则是六个字母的有趣函数名称...所以,最终,选择你自己喜欢的方式。^_^ - paercebal
14
使用C++标准库的命名规范的一个优点是,您自己编写的容器类更容易与STL容器兼容。例如,您可以在具有push_back()方法的类上使用back_insert_iterator,但不能在具有pushBack()方法的类上使用。 - Emile Cormier

5

为什么需要协调?只要代码编译通过,能够完成工作,就不必担心。


17
对于某些人(比如我),作为程序员的乐趣之一是代码的美学。只要不妨碍手头任务的完成,我的代码就像诗歌一样优美动人。 - Gregory Higley
1
在不同的代码约定中,你必须记住标识符来自哪里,以便正确地输入它。 - Diomidis Spinellis
是的,但是当处理其他人的代码和第三方库时,他们不可能有与您(以及彼此)相同的约定,因此在某些时候,您只需要咬紧牙关,适应它,并完成一些工作。 - Jim Buck
1
Diomidis Spinellis在另一个评论串中提到,他被Java的绝对命名约定宠坏了。我也曾因为被Java和Ruby的严格命名约定宠坏了而有过同样的疑问。正如我们在这里都学到的那样,C++是一种难以调和的惯例混合体。 - EnabrenTane
1
作为开发人员,我们大部分时间都在阅读代码。约定使得这一部分工作变得更加高效和安全。无法将这些约定强制应用于第三方库并不是问题:你几乎不会阅读/调试第三方库的代码。如果第三方库接口语义存在冲突,你可以适应它,或者在代码中留下注释。在处理其他人的代码时,约定是让他们遵循与你相同规则的关键。 - IInspectable

4

在编写代码时,我倾向于追求完美的代码风格,但这常常让我感到困扰。虽然我希望有一个通用的标准,但实际上并没有。在我的职业生涯中,我发现只要在同一个项目中的程序员保持一致性,那就是最好的结果。

最终,我认为它归结于知道一个方法、对象或函数来自哪个库。如果你知道了这一点,那么就容易记住该库使用的约定,前提是项目没有包含大量的库。我曾经尝试过使自己的代码与我使用的库相匹配,但这永远都是一个不断变化的目标,并且最终只会让人感到沮丧。


4
说实话,我会直接使用这个库并坚持自己的编码风格。你可以将它包装起来,但那似乎有些过头了。

3

在我所从事的项目中,我遵循着项目的编码规范。当我调用其他内容时,我使用该库的API。

我还想强调一点,包装库是个坏主意(在我所从事的代码库中有很多这样的例子),因为通常是由解决自己问题的开发人员完成的,而且通常不适合其他开发人员使用。另一方面,高质量的包装是昂贵的。


2

喜爱的名言:

标准最好的一点就是,有如此之多的选择!

我建议您采用在公司代码中最常见的库惯例(很可能是C++库,我相信Boost也遵循这个惯例),并将其作为您的标准。否则,您可能就没有任何标准可言。


2

既然无法改变标准库的实现方式,我想我们就只能忍受它了。至于协调 - 前段时间,我在编写一些Win32 API代码时,尝试使用PascalCasing来命名自己的方法,因为API中也是这样做的,但那种感觉并不适合我。所以我回到了使用camelCase命名我的方法。我同意这是一团糟,但其他选择是为每个新的框架或库调整你的风格,还有你提到的问题,即在单个项目中有多个库使用不同的惯例。所以我的建议是 - 照着自己的方法和类感觉对的去做。或者,在公司环境中 - 遵循公司的最佳实践和指南。


吹毛求疵:我不认为“camelCase”这个术语在区分首字母的大小写方面被广泛使用。见:http://en.wikipedia.org/wiki/Camelcase。我很少见到“PascalCase”这个术语——也不知道它的一般含义是什么。 - Steve Fallows
@Steve:你有读过你提供的那篇维基百科文章吗?因为在开头它提到了驼峰命名法和帕斯卡命名法之间的区别,说它被“一些人”使用。嗯,我就是其中之一。 - Boyan
这是有关大小写风格的良好参考,位于MSDN上:http://msdn.microsoft.com/zh-cn/library/x2dbyw72(VS.71).aspx - Boyan
糟糕 - 我看得太快了。在其他的阅读中,我发现我的经验(camelCase作为一个更通用的术语)并不是最常见的。这就是我挑剔的后果。 :) - Steve Fallows

2

我记得很久以前曾经读到过,他们故意选择将标准库与推荐的编码规范区分开来,以避免命名冲突。然而,现在我找不到任何提到这一点的参考资料了。我记得读过,你不应该在类型名称中使用首字母小写,因为它们是保留给标准库的。我认为下划线的使用也可能类似。我并不认为多种命名约定是一个问题,因为它明确地将标准代码与项目中的代码分开。我总是使用大驼峰式命名法来编写类型和小驼峰式命名法来编写方法/成员。我的当前工作场所还使用大驼峰式命名法来编写方法,这让我非常不爽。但是,他们也喜欢匈牙利命名法,即使微软已经放弃了它 :P


1

你应该接受差异的存在。

当人们看到 remove_copy_if 的使用时,他们会立刻知道这是一个算法。这实际上是一个积极的特征,因为算法带有某些保证(或缺乏保证)。

我们还为自己的自定义算法使用命名约定。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接