【问题标题】:What is a good naming convention for vars, methods, etc in C++? [closed]C++ 中变量、方法等的良好命名约定是什么? [关闭]
【发布时间】:2010-09-14 05:48:49
【问题描述】:

我来自 Objective-C 和 Cocoa 世界,那里有很多约定,很多人会说它让你的代码更漂亮! 现在用 C++ 编程我找不到像这样的 C++ 好的文档。

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html

标准 C++ 可能没有上述内容,但我希望我可以坚持其他一些 SDK 或 API(如 Microsoft(?)等)约定。

希望你能给我一些链接。

【问题讨论】:

  • 我保证对任何建议匈牙利语的人投反对票。
  • @AShelly:阅读 Joel Spoolsky 关于匈牙利符号的帖子,它可能会改变你的想法。我不同意他的观点,但这篇文章还是值得的,因为它解释了对这个计划的巨大误解。
  • 我保证对任何建议 Google 约定的人投反对票。
  • @Matthieu:Joel 的建议对 C 有好处,但是如果您使用 C++ 并且认真对待 Joel 建议的事情,例如当您错误地尝试转换一行到一列(我相信这是他用的例子)。
  • @Matthieu:我读过它,我支持“让错误的代码看起来不正确”的目标。我应该明确表示我反对“匈牙利系统”,它不符合这个目的,或者我能看到的任何其他目的。

标签: c++ naming-conventions


【解决方案1】:

做任何你想做的事情,只要它最小、一致和doesn't break any rules

就个人而言,我发现 Boost 风格最简单;它与标准库匹配(给代码一个统一的外观)并且很简单。我个人分别为成员和参数添加了mp 前缀,给出:

#ifndef NAMESPACE_NAMES_THEN_PRIMARY_CLASS_OR_FUNCTION_THEN_HPP
#define NAMESPACE_NAMES_THEN_PRIMARY_CLASS_OR_FUNCTION_THEN_HPP

#include <boost/headers/go/first>
#include <boost/in_alphabetical/order>
#include <then_standard_headers>
#include <in_alphabetical_order>

#include "then/any/detail/headers"
#include "in/alphabetical/order"
#include "then/any/remaining/headers/in"
// (you'll never guess)
#include "alphabetical/order/duh"

#define NAMESPACE_NAMES_THEN_MACRO_NAME(pMacroNames) ARE_ALL_CAPS

namespace lowercase_identifers
{
    class separated_by_underscores
    {
    public:
        void because_underscores_are() const
        {
            volatile int mostLikeSpaces = 0; // but local names are condensed

            while (!mostLikeSpaces)
                single_statements(); // don't need braces

            for (size_t i = 0; i < 100; ++i)
            {
                but_multiple(i);
                statements_do();
            }             
        }

        const complex_type& value() const
        {
            return mValue; // no conflict with value here
        }

        void value(const complex_type& pValue)
        {
            mValue = pValue ; // or here
        }

    protected:
        // the more public it is, the more important it is,
        // so order: public on top, then protected then private

        template <typename Template, typename Parameters>
        void are_upper_camel_case()
        {
            // gman was here                
        }

    private:
        complex_type mValue;
    };
}

#endif

那个。 (就像我在 cmets 中所说的那样,不要为您的代码采用 Google 样式指南,除非它是为了像命名约定这样无关紧要的东西。)

【讨论】:

  • 嘿!你潜入你的括号式偏好!就我个人而言,即使是单行语句,我也更喜欢使用大括号,很容易搞砸缩进(当人们无意中使用另一个制表符/空格设置进行编辑时)并且大括号使范围变得明显,因此您不必怀疑以下内容是否行是否属于该块...
  • 我的也是类似的。唯一的区别。类型以大写字母开头。其他所有内容都以小写字母开头(只是我的怪癖)。
  • @Matthieu:哈,我不会放弃这个机会。 :) 我曾经虔诚地捍卫总是戴牙套,但现在我发现省略它们更干净。 (通常,单个语句是 return; 或一些微不足道的东西)。
  • 我同意马修的观点。永远用牙套!!当我年轻天真时,我讨厌牙套,我认为牙套会弄乱我的密码。现在,当我年纪大了,变得更聪明了,我就会遵守规则,总是清楚地表达我的意图。将大括号放在单衬里是这样做的一部分。
  • 我一直在寻找有关 Boost 命名约定的文档,但只能找到这个:boost.org/development/requirements.html您是通过使用它学习的还是读过一些东西?
【解决方案2】:

可能有多少个人就有多少命名约定,关于使用哪种括号样式等等的争论无休无止(而且毫无结果)。

所以我有两个建议:

  • 在项目中一致
  • 不要使用保留标识符(任何带有两个下划线或以下划线开头后跟一个大写字母的标识符)

剩下的看你自己了。

【讨论】:

  • +1 表示“保持一致”;这是最重要的一条规则(也是唯一一条你可能会让每个人都同意的规则)。
  • +1 保留标识符,只是因为编译器现在没有使用它并不意味着下一个版本不会
【解决方案3】:

我实际上经常使用 Java 风格:PascalCase 用于类型名称,camelCase 用于函数和变量,CAPITAL_WORDS 用于预处理器宏。我更喜欢 Boost/STL 约定,因为您不必使用 _type 为类型添加后缀。例如

Size size();

而不是

size_type size();   // I don't like suffixes

StackOverflow 代码格式化程序将 Size 识别为类型名称的额外好处 ;-)

【讨论】:

  • 很好的例子,清晰易读
【解决方案4】:

我们遵循此页面上列出的准则:C++ Programming Style Guidelines


我还建议您阅读The Elements of C++ Style by Misfeldt et al,这是一本关于这个主题的优秀书籍。

【讨论】:

  • 我可以使用您的 FIRST 链接中引用的文档作为我开始的项目的指导文档吗?
  • @HomunculusReticulli,是的。
  • 谢谢!,非常感谢! (也应该让生活更轻松)!顺便说一句,我应该在文本底部等处注明出处吗? - 如果是,我应该归咎于谁?
  • @HomunculusReticulli,我不隶属于该页面/文档。如果您觉得它有帮助并决定使用它,我建议您包含一个指向该页面的链接。
【解决方案5】:

不管怎样,C++ 的原作者 Bjarne Stroustrup 有他自己喜欢的风格,在这里描述:http://www.stroustrup.com/bs_faq2.html

【讨论】:

    【解决方案6】:

    虽然很多人会建议或多或少严格的 Hungarian notation 变体 (scary!),但对于命名建议,我建议您查看 Google C++ Coding Guidelines。这可能不是最流行的命名约定,但至少它相当完整。除了合理的命名约定外,还有一些有用的指导方针,但其中大部分内容应持保留态度(例如例外禁令,以及远离现代 C++ 编码风格的趋势)。

    虽然我个人喜欢 STL 和 Boost 的技术含量极低的约定风格;)。

    【讨论】:

    • Google 的 C++ 编码指南很糟糕,不要采用它们。 (除了命名约定这样无关紧要的东西。)Google 风格指南是现代 C++ 代码的对立面。
    • @GMan:我同意,Google 指南专门用于向后兼容其现有的 C 代码库(如指南中明确提到的)。对于一个新项目,它们是可能发生的最糟糕的事情之一。
    • @GMan,这也是我最初的想法,但对文档的更仔细研究让我意识到它在给专业人士留一些喘息的空间和(更重要的是)不允许新手之间取得了很好的平衡开发商自爆。你不能指望在任何地方都拥有一支优秀的现代 C++ 编码员团队——即使是一个糟糕的编码员也可能在没有严格指导的情况下毁掉一个好的代码库......
    • @GMan:您能否明确说明您在 Google 指南中发现的糟糕之处?我现在正在阅读它,一些建议似乎很不错。
    • @Martin,我同意例外条款很荒谬;)
    【解决方案7】:

    一致性和可读性(自记录代码)很重要。一些线索(如案例)可以而且应该用于避免冲突,并指示是否需要实例。

    我采用的最佳实践之一是使用代码格式化程序(astyle 和 uncrustify 是 2 个示例)。代码格式化程序可以破坏您的代码格式化 - 配置格式化程序,让它完成它的工作。认真地,忘记手动格式化并开始使用它们的实践。他们将节省大量时间。

    如前所述,命名时要非常具有描述性。此外,范围界定非常具体(类类型/数据/命名空间/匿名命名空间)。总的来说,我真的很喜欢 java 的很多常见书写形式——这是一个很好的参考,类似于 c++。

    至于具体的外观/命名,这是一个与我使用的类似的小示例(变量/参数是 lowerCamel,这仅展示了语言的一部分功能):

    /** MYC_BEGIN_FILE_ID::FD_Directory_nanotimer_FN_nanotimer_hpp_::MYC_BEGIN_FILE_DIR::Directory/nanotimer::MYC_BEGIN_FILE_FILE::nanotimer.hpp::Copyright... */
    #ifndef FD_Directory_nanotimer_FN_nanotimer_hpp_
    #define FD_Directory_nanotimer_FN_nanotimer_hpp_
    
    /* typical commentary omitted -- comments detail notations/conventions. also, no defines/macros other than header guards */
    
    namespace NamespaceName {
    
    /* types prefixed with 't_' */
    class t_nanotimer : public t_base_timer {
        /* private types */
        class t_thing {
            /*...*/
        };
    public:
        /* public types */
        typedef uint64_t t_nanosecond;
    
        /* factory initializers -- UpperCamel */
        t_nanotimer* WithFloat(const float& arg);
        /* public/protected class interface -- UpperCamel */
        static float Uptime();
    protected:
        /* static class data -- UpperCamel -- accessors, if needed, use Get/Set prefix */
        static const t_spoke Spoke;
    public:
        /* enums in interface are labeled as static class data */
        enum { Granularity = 4 };
    public:
        /* construction/destruction -- always use proper initialization list */
        explicit t_nanotimer(t_init);
        explicit t_nanotimer(const float& arg);
    
        virtual ~t_nanotimer();
    
        /*
           public and protected instance methods -- lowercaseCamel()
           - booleans prefer is/has
           - accessors use the form: getVariable() setVariable().
           const-correctness is important
         */
        const void* address() const;
        virtual uint64_t hashCode() const;
    protected:
        /* interfaces/implementation of base pure virtuals (assume this was pure virtual in t_base_timer) */
        virtual bool hasExpired() const;
    private:
        /* private methods and private static data */
        void invalidate();
    private:
        /*
           instance variables
           - i tend to use underscore suffix, but d_ (for example) is another good alternative
           - note redundancy in visibility
         */
        t_thing ivar_;
    private:
        /* prohibited stuff */
        explicit t_nanotimer();
        explicit t_nanotimer(const int&);
    };
    } /* << NamespaceName */
    /* i often add a multiple include else block here, preferring package-style inclusions */    
    #endif /* MYC_END_FILE::FD_Directory_nanotimer_FN_nanotimer_hpp_ */
    

    【讨论】:

    • 你肯定喜欢小写的;D
    • @bluish ...不喜欢碰撞:)
    【解决方案8】:

    人们在编写 C++ 代码时使用了许多不同的风格/惯例。例如,有些人喜欢使用大写字母(myVar 或 MyVar)或下划线(my_var)来分隔单词。通常,使用下划线的变量都是小写的(根据我的经验)。
    还有一种称为匈牙利语的编码风格,我相信它是微软使用的。我个人认为这是浪费时间,但它可能会被证明是有用的。这是为变量名称赋予短前缀,例如 i 或 f 以提示变量类型。例如:int iVarname, char* strVarname.

    可以接受以 _t 结尾的结构/类名称,以将其与变量名称区分开来。例如:

    class cat_t {
      ...
    };
    
    cat_t myCat;
    

    通常也接受添加一个词缀来表示指针,例如pVariable或variable_p。

    总而言之,确实没有任何单一的标准,而是有很多。您对变量命名所做的选择并不重要,只要它是可以理解的,最重要的是,它是一致的。一致性,一致性,一致性! (尝试输入三次!)

    如果一切都失败了,谷歌它。

    【讨论】:

    • 以 '_t' 结尾的 每个 类命名将是彻头彻尾的邪恶......
    • 用于作为数据类型的类。
    • @KornelKisielewicz 可能是用作域对象的类(回复很晚)。 std::string 是一种数据类型(与intdouble 的用法类似); bank_account 是域对象(并且不是)。
    【解决方案9】:

    真的没关系。只要确保描述性地命名变量和函数即可。还要保持一致。

    现在比看到这样的代码更糟糕:

    int anInt;                  // Great name for a variable there ...
    int myVar = Func( anInt );  // And on this line a great name for a function and myVar
                                // lacks the consistency already, poorly, laid out! 
    

    编辑:正如我的评论者所指出的,需要在整个团队中保持一致性。因此,只要保持一致性,您选择哪种方法并不重要。然而,没有正确或错误的方法。我工作过的每个团队都有不同的想法,我已经适应了这些想法。

    【讨论】:

    • 这很重要。你说话的方式就像你以前从未在团队中工作过一样。
    • 好吧,只要它的描述性和一致性都没有关系……是的,在一个团队中,这意味着在整个团队中保持这种一致性。我会更新我的答案。
    【解决方案10】:

    不像您提供的链接那么简洁:但以下第 14 - 24 章可能会有所帮助:) 呵呵

    参考:http://www.amazon.com/Coding-Standards-Rules-Guidelines-Practices/dp/0321113586/ref=sr_1_1?ie=UTF8&s=books&qid=1284443869&sr=8-1-catcorr

    【讨论】:

    • 只是浏览了一下,几乎没有关于在那里命名的内容(除了明显的_like_dont_do_too_long_and_useless_variable_names...)
    • 哇...你是对的。我在考虑“结构”约定而不是命名约定,因为我没有试图理解您的问题并阅读您提供的链接。
    • 这本书是关于有助于提高代码质量的编程风格元素,以及命名约定等不相关的细节在第 0 条中总结:不要出汗小东西(或:知道什么不要标准化)。如果您觉得有必要将不相关的细节标准化,这将无济于事。
    猜你喜欢
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    相关资源
    最近更新 更多