《华为C语言通用编程规范.docx》由会员分享,可在线阅读,更多相关《华为C语言通用编程规范.docx(64页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、章节内容0前言目的重点关注约定例外1原则好代码的原则类和函数设计指导原则保证静态类型安全遵循C+ ISO标准优先编译时检查错误使用命名空间来限定作用域优先使用C+特性而不是C特性2命名通用命名文件命名函数命名类型命名变量命名宏、常量、枚举命名3格式行宽缩进大括号函数声明和定义函数调用if语句循环语句switch语句表达式变量赋值初始化指针和引用编译预处理空格和空行类4注释注释风格文件头注释函数头注释代码注释5头文件头文件职责头文件依赖6作用域命名空间全局函数和静态成员函数全局变量全局常量和静态成员常量7类构造、拷贝构造、赋值和析构函数继承多重继承重载8函数函数设计内联函数函数参数9 C+其常量
2、与初始化表达式类型转换资源分配和释放标准库const的用法异常他特性模板宏10现代代码简洁性和安全性提升智能指针Lambda接口C+特性。前言目的规则并不是完美的,通过禁止在特定情况下有用的特性,可能会对代码实现造成影响。但是我们制定规则的目的为了大多数程序员可以得到更多的好处如果在团队运作中认为某个规则无法遵循,希望可以共同改进该规则。参考该规范之前,希望您具有相应的C+基础能力,而不是通过该文档来学习C+。1.了解C+的ISO标准;2.熟知C+的基本语言特性,包括C+03/11/14/17相关特性;3.了解C+的标准库;重点关注1 约定C+的编程风格,比如命名,排版等。2 C+的模块化设计
3、,如何设计头文件,类,接口和函数。3 C+相关特性的优秀实践,比如常量,类型转换,资源管理,模板等。4 现代C+的优秀实践,包括C+11/14/17中可以提高代码可维护性,提高代码可靠性的相关约定。约定规则:编程时必须遵守的约定(must)建议:编程时应该遵守的约定(should)本规范适用通用C+标准,如果没有特定的标准版本,适用所有的版本(C+03/11/14/17),例外无论是规则还是建议,都必须理解该条目这么规定的原因,并努力遵守。但是,有些规则和建议可能会有例外。在不违背总体原则,经过充分考虑,有充足的理由的前提下,可以适当违背规范中约定。例外破坏了代码的一致性,请尽量避免。规则的例
4、外应该是极少的。下列情况,应风格一致性原则优先:修改外部开源代码、第三方代码时,应该遵守开源代码、第三方代码已有规范,口持风格结一某些特定M域:优先参考其行业规范。1原则好代码的原则我们参考Kent Beck的简单设计四原则来指导我们的如何写出优秀的代码,如何有效地判断我们的代码是优秀的。1.通过所有测试(Passes its tests)2.尽可能消除重复(Minimizes duplication)3.尽可能清晰表达(Maximizes clarity)4.更少代码元素(Has fewer elements)5.以上四个原则的重要程度依次降低。这组定义被称做简单设计原则。第一条强调的是外部
5、需求,这是代码实现最重要的;第二点就是代码的模块架构设计,保证代码的正交性,保证代码更容易修改;第三点是代码的可阅读性,保证代码是容易阅读的;最后一点才是保证代码是简洁的,在简洁和表达力之间,我们更看重表达力。类和函数设计指导原则C+是典型的面向对象编程语言,软件工程界已经有很多OOP原则来指导我们编写大规模的,高可扩展的,可维护性的代码:-高内聚,低耦合的基本原则- SOLID原则-迪米特法则-Tell, Don,task原则-组合/聚合复用原则保证静态类型安全我们希望C+应该是静态类型安全的,这样可以减少运行时的错误,提高代码的健壮性。但是由于C+的下面的特性存在,会破坏C+静态类型安全,
6、我们针对这部分特性要仔细处理。unions联合体类型转换cast -缩窄转换narrowing conversions -类型退化type decay -范围错误range errors-void*类型指针我们可以通过约束这些特性的使用,或者使用C+的新特性,比如variant(C+17), GSL的span, narrow_cast等来解决这些问题,提高C+代码的健壮性。遵循C+ISO标准希望通过使用ISO C+标准的特性来编写C+代码,对于ISO标准中未定义的或者编译器实现的特性要谨慎使用,对于GCC等编译器的提供的扩展特性也需要谨慎使用,这些特性会导致代码的可移植性比较差。注意:如果模块
7、中需要使用相关的扩展特性来,那么尽可能将这些特性封装成独立的接口,并且可以通过编译选项关闭或者编译这些特性。对于这些扩展特性的使用,请模块制定特性编程指南来指导这些特性的使用。优先编译时检查错误通过编译器来优先保证代码健壮性,而不是通过编写错误处理代码来处理编译就可以发现的异常,比如: 通过const来保证数据的不变性,防止数据被无意修改。 通过gsl:span等来保证char数组不越界,而不是通过运行时的length检查。 通过static_assert来进行编译时检查。使用命名空间来限定作用域全局变量,全局常量和全局类型定义由于都属于全局作用域,在项目中,使用第三方库中容易出现冲突。命名空
8、间将作用域细分为独立的,具名的作用域,可有效地防止全局作用域的命名冲突。1. class, struct等都具有自己的类作用域。2.具名的namespace可以实现类作用域更上层的作用域。3.匿名namespace和static可以实现文件作用域。对于没有作用域的宏变量,宏函数强烈建议不使用。作用域的一些缺点:1.虽然可以通过作用域来区分两个命名相同的类型,但是还是具有迷惑性。2.内联命名空间会让命名空间内部的成员摆脱限制,让人迷惑。3.通过多重嵌套来定义namespace,会让完整的命名空间比较冗长。所以,我们使用命名空间的建议如下:-对于变量,常量和类型定义尽可能使用 namespace,
9、减少全局作用域的冲突-不要在头文件中使用using namespace -不要使用内联命名空间-鼓励在.cpp文件中通过匿名namespace或者static集封装,防止不必要的定义通过API暴露出去。优先使用C+特性而不是C特性C+比起c语言更加类型安全,更加抽象。我们更推荐使用C+的语言特性来编程,比如使用string而不是char*,使用vector而不是原生数组,使用namespace而不是 static o通用命名常见命名风格有:驼峰风格(CamelCase)大小写字母混用,单词连在一起,不同单词间通过单词首字母大写来分开。按连接后的首字母是否大写,又分:大驼峰(UperCamelC
10、ase)和小驼峰(lowerCamelCase)内核风格(unixike)单词全小写,用下划线分割如:test_result匈牙利风格在大驼峰的基础上,加上前缀;前缀用于表达类型或用途。如:iSavedCount,Tested,规则2.1.1标识符命名使用驼峰风格命名风格大驼峰大驼峰(接口部分可加 前缀,如XXX一函数 名)小驼峰k+大小写混合 大写+下划线 全小写不考虑匈牙利命名,在内核风格与驼峰风格之间,根据存量代码的情况,我们选择驼峰风格。类型类类型,结构体类型,枚举类型,联合体类型等类型定义函数(包括全局函数,作用域函数,成员函数)全局变量(包括全局和命名空间域下的变量,类静态变量),
11、局部变量,函数参数,类、结构体和联合体中的成员变量常量(const),枚举值宏命名空间注意:上表中常量是指全局作用域、namespace域、类的静态成员域下,以 const或constexpr修饰的基本数据类型、枚举、字符串类型的变量。上表中_变量是指除常量定义以外的其他变量,均使用小驼峰风格。文件命名建议2.2.1 C+文件以.cpp结尾,头文件以.h结尾我们推荐使用.h作为头文件的后缀,这样头文件可以直接兼容C和C+。我们推荐使用.cpp作为实现文件的后缀,这样可以直接区分C+代码,而不是C代码。目前业界还有一些其他的后缀的表示方法: 头文件:.hh,.hpp,.hxx cpp 文件:.c
12、c,.cxx,.C对于本文档,我们默认使用.h和.cpp作为后缀。建议2.2.2 C+文件名和类名保持一致C+的头文件和cpp文件名和类名保持一致,使用下划线小写风格。如下:-database_connection.h - database_connection.cpp结构体,命名空间,枚举等定义的文件名类似。函数命名函数命名统一使用大驼峰风格,一般采用动词或者动宾结构。接口部分可加前缀,如XXX一函数名。class List public:void AddElement(const Elements element);Element GetElement(const unsigned int
13、 index) const;bool IsEmpty() const;bool MCC_GetClass(););namespace utils voidDeletellser();类型命名类型命名采用大驼峰命名风格。所有类型命名一一类、结构体、联合体、类型定义(typedef)、枚举使用相同约定,例如:/ cLasseSj structs and unionsclass UrlTable ,class UrlTableTester .struct UrlTableProperties union Packet / typedefstypedef std:map PropertiesMap;/
14、 enumsenum UrlTableErrors .对于命名空间的命名,建议全小写:/ namespacenamespace osutils namespace fileutils 建议2.4.1避免滥用typedef或者#define对基本类型起别名除有明确的必要性,否则不要用typedef/#define对基本数据类型进行重定义。优先使用头文件中的基本类型:有符号类型无符号类型描述int8_tuint8_t宽度恰为8的有/无符号整数类型intl6_tuintl6_t宽度恰为16的有/无符号整数类型int32_tuint32_t宽度恰为32的有/无符号整数类型int64_tuint64_t
15、宽度恰为64的有/无符号整数类型intptr_tuintptr_t足以保存指针的有/无符号整数类型如果模块有自己的定义,请使用统一的typedef来定义类型:typedef signed char VOS_INT8;typedef unsigned char VOS_U工NT8;#if_WORDSIZE =64typedef unsigned long int VOS_UINTPTR;#elsetypedef unsigned intVOS_UINTPTR;#endif如果模块为了封装某个类型的信息,方便后续的扩展,可以使用typedef来重新定义。typedef uint8_t Device
16、lD;/./若干版本后扩展成16-bittypedef uintl6_t DevicelD;有特殊作用的类型typedef void *Handle;注意:不要使用#define进行别名定义,并且在C+11以后推荐使用using来定义类型。除上述理由外,应避免给其本数值类型别名定义。因为类型别名可读性并不好,隐藏了基本数值类型信息,如位宽,是否带符号。滥用举例:typedef uintl6_t MyCounter;.int Foo() MyCounterc;-while (c =0) printf(counter =%dnC);/.)/.)对,MyCounter,是否可能小于0,打印时用,d,
17、还是,u,都不是很直观,极容易引入上述类似缺陷。变量命名通用变量命名采用小驼峰,包括全局变量,函数形参,局部变量,成员变量。std: string tableName;/ Good:推荐此风格std: string tablename;/ Bad:禁上此风格std:string path;/ Good:只仃个中.词时,小,花岭为的小写规则251类的成员变量命名使用小驼峰。class Foo private:std: string fileName;/不潦加任何作用域前缀或者后缀;当构造函数参数和成员变量重名时,可通过this,来引用成员变量。class MyClass public:MyCla
18、ss(int myVar): myVar(myVar)/ OK,初始化列表允许同人参初始化同名成员if (NeedNewVar()this-myVar = GetValue();/;匕起不要漏掠.否则就成给人医赋值)private:int myVar;宏、常量、枚举命名宏采用全大写,下划线连接的格式。常量、枚举值使用k+大小写混合。函数局部 const常量和类的普通const成员变量,使用小驼峰命名风格。ftdefine MAX(a, b)(a)(b)?(b):(a)/仅对宏命冬举例,并不推荐用宏实现此类功能enum TintColor /注意,枚举类型启用大驼峰,其下面的取值是大小7混合kR
19、edjkDarkRedjkGreen,kLightGreen;int Func(.)const unsigned int buffersize =100;/函数局部常/char *p = new charbufferSize;.namespace utils const unsigned int kFileSize =200;/企局常止)3格式尽管有些编程的排版风格因人而异,但是我们强烈建议和要求使用统一的编码风格,以便所有人都能够轻松的阅读和理解代码,增强代码的可维护性。行宽建议3.1.1行宽不超过120个字符建议每行字符数不要超过120个。如果超过120个字符,请选择合理的方式进行换行。例
20、外:如果一行注释包含了超过120个字符的命令或URL,则可以保持一行,以方便复制、粘贴和通过grep查找;包含长路径的include语句可以超出120个字符,但是也需要尽量避免;编译预处理中的error信息可以超出一行。预处理的error信息在一行便于阅读和理解,即使超过120个字符。#ifndef XXX_YYY_ZZZ#error Header aaaa/bbbb/cccc/abc.h must only be included after xxxx/yyy y/zzzz/xyz . h, because xxxxxxxxxxxxxxxxxxxxxxxxxxxxx#endif缩进规则3.2
21、.1使用空格进行缩进,每次缩进2个空格只允许使用空格(space)进行缩进,每次缩进为2个空格。大括号规则3.3.1除函数外,使用K&R缩进风格函数左大括号跟随语句放行末。右大括号独占一行,除非后面跟着同一语句的剩余部分,如do语句中的while,或者if语句的else/else if,或者逗号、分号。如:struct MyType /跟随语句放行末.前置1空格int Foo(int a)/函数左人括号跟随语句放行木if (.) else )推荐这种风格的理由: 代码更紧凑; 相比另起一行,放行末使代码阅读节奏感上更连续; 符合后来语言的习惯,符合业界主流习惯; 现代集成开发环境(IDE)都具
22、有代码缩进对齐显示的辅助功能,大括号放在行尾并不会对缩进和范围产生理解上的影响。对于空函数体,可以将大括号放在同一行: class MyClass public:MyClass(): value(0)private:int value;函数声明和定义规则341函数声明和定义的返回类型和函数名在同一行;函数参数列表超出行宽时要换行并合理对齐在声明和定义函数的时候,函数的返回值类型应该和函数名在同一行;如果行宽度允许,函数参数也应该放在一行;否则,函数参数应该换行,并进行合理对齐。参数列表的左圆括号总是和函数名在同一行,不要单独一行;右圆括号总是跟随最后一个参数。换行举例:ReturnType F
23、unctionName(ArgType paramNamel, ArgType paramName2)/ G ood:全港同一行.ReturnType VeryVeryVeryLongFunctionName(ArgType paramNamel不满足所有参数,进行换行ArgType paramNameZ/ Good:和上一行参数对齐ArgType paramName3)ReturnType LongFunctionName(ArgType paramNamel, ArgType paramName2,/行宽限制,进行换行ArgType paramName3, ArgType paramNam
24、e4, ArgType paramName5)/ Good:换行后4空格缩进.ReturnType ReallyReallyReallyReallyLongFunctionName(不满足第1个参数,直接换行ArgType paramNamel, ArgType paramName2, ArgType paramName3)/ Go od:换行房4空格缩进函数调用规则3.5.1函数调用入参列表应放在一行,超出行宽换行时,保持参数进行合理对齐函数调用时,函数参数列表放在一行。参数列表如果超过行宽,需要换行并进行合理的参数对齐。左圆括号总是跟函数名,右圆括号总是跟最后一个参数。换行举例:Retur
25、nType result = FunctionNameCparamNamel, paramName2);/ Good:函数参数放在一行ReturnType result = FunctionName(paramNameljparamName2,/ Good:保持与上方参数对齐paramName3);ReturnType result = FunctionName(paramNamel, paramName2,paramName3, paramName4, paramNameS);/ Good:参数换行,4空格缩进ReturnType result = VeryVeryVeryLongFunct
26、ionName(/行宽不满足第1个参数,直接换行paramNamel, paramName2, paramName3);/换行后,4空格缩进如果函数调用的参数存在内在关联性,按照可理解性优先于格式排版要求,对参数进行合理分组换行。/ Good:每行的参数代表一组相关性较强的数据结构.放在一行便于理解int result = DealWithStructureLikeParams(left.x, left.y,/表,-相关参数right.x, right.y);/我示另外一组相关参数if语句规则3.6.1 if语句必须要使用大括号我们要求if语句都需要使用大括号,即便只有一条语句。理由:-代码逻
27、辑直观,易读;-在已有条件语句代码上增加新代码时不容易出错;-对于在if语句中使用函数式宏时,有大括号保护不易出错(如果宏定义时遗漏了大括号)。if (objectlsNotExist)/ Good:单.仃条件语句也加大括号return CreateNewObject();)规则3.6.2禁止if/else/else if写在同一行条件语句中,若有多个分支,应该写在不同行。如下是正确的写法:if (someConditions) DoSomething(); else / Good: eLse 与 if 在不同行下面是不符合规范的案例:if (someConditions). else ./
28、Bad: eLse 与 if 在同一行循环语句规则3.7.1循环语句要求使用大括号和if语句类似,我们要求for/while循环语句必须加上的大括号,即使循环体是空的,或者循环语句只有一条。for (int i =0; i someRange; i+) DoSomething();)如果循环体是空的,应该使用空的大括号,而不是使用单个分号。单个分号容易被遗漏,也容易被误认为是循环语句中的一部分。for (int i =0; i someRange; i+)/ Good: for 循环体是E,使用大括号,而不是使用分号while (someCondition)/ Good: whiLe循环体是个
29、:,使用大括号,而不是使用分号while (someCondition)continue;/ Good: continue太小个逻辑,可以使用大括号-也可以不使用坏的例子:for (int i =0; i threshold &/ Good:换行后,逻钳操作汾放住行尾 someConditionsion) DoSomething();int result = reallyReallyLongVariableNamel +/ GoodreallyReallyLongVariableName2;表达式换行后,注意保持合理对齐,或者4空格缩进。参考下面例子int sum = longVaribleN
30、amel + longVaribleName2+ longVaribleName3+ longVaribleName4+ longVaribleNameS + longVaribleName6;/Good:4空格缩进int sum = longVaribleNamel + longVaribleName2+ longVaribleName3+ longVaribleName4+ longVaribleNameS + longVaribleNameS;/Good:保持对齐变量赋值规则3.10.1多个变量定义和赋值语句不允许写在一行每行只有一个变量初始化的语句,更容易阅读和理解。int maxCo
31、unt =10;bool isCompleted = false;下面是不符合规范的示例:int maxCount =10; bool isCompleted = false;/ Bad:公址初始化7,开放在多行,每行一个变量初始化int x, y =0;/ Bad:多个变量定义需要分行,每行一个int pointX;int pointY;pointX =1; pointY =2;/ Bad:多个变赋值语旬放同一行例外:for循环头、if初始化语句(C+17)、结构化绑定语句(C+17)中可以声明和初始化多个变量。这些语句中的多个变量声明有较强关联,如果强行分成多行会带来作用域不一致,声明和初
32、始化割裂等问题。初始化初始化包括结构体、联合体、及数组的初始化规则3.11.1初始化换行时要有缩进,并进行合理对齐结构体或数组初始化时,如果换行应保持4空格缩进。从可读性角度出发,选择换行点和对齐位置。const int rank=16,16,16,16,32,32,32,32,64,64,64,64,32,32,32,32;指针与引用建议3.12.1指针类型“*”跟随变量名或者类型,不要两边都留有或者都没有空格指针命名:*靠左靠右都可以,但是不要两边都有或者都没有空格。int* p = NULL;/ Goodint *p = NULL;/ Goodint*p = NULL;/ Badint
33、* p = NULL;/ Bad例外:当变量被const修饰时,*”无法跟随变量,此时也不要跟随类型。char * const VERSION =V100;建议3.12.2引用类型&跟随变量名或者类型,不要两边都留有或者都没有空格引用命名:&靠左靠右都可以,但是不要两边都有或者都没有空格。int i =8;int& p = i;/ Goodint &p = i;/ Goodint & p = i;/ Badint&p = i;/ Bad编译预处理规则3.13.1编译预处理的#统一放在行首,嵌套编译预处理语句时,*不缩进编译预处理的#统一放在行首,即使编译预处理的代码是嵌入在函数体中的,#也应该
34、放在行首。#if defined(_x86_64_)& defined(_GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)/ Good:放茬行皆#define ATOMIC_X86_HAS_CMPXCHG16B 1/ Good:放在行首#else#define ATOMIC_X86_HAS_CMPXCHG16B 0#endifint FunctionName()if (someThingError)#ifdef HAS_SYSLOG/ Good:即便在函数内部,也放在行首WriteToSysLog();#elseWriteToFileLog();#endif 内嵌的预处理语
35、句#不缩进#if defined(_x86_64_)& defined(_GCC_HAVE_SYNC_C0MPARE_AND_SWAP_16)ftdefine ATOMIC_X86_HAS_CMPXCHG16B 1/ Good:区分层次,便于阅读#else#define ATOMIC_X86_HAS_CMPXCHG16B 0#endif空格和空行建议3.14.1水平空格应该突出关键字和重要信息,避免不必要的留白水平空格应该突出关键字和重要信息,每行代码尾部不要加空格。总体规则如下: if, switch, case, do, while, for 等关键字之后加空格; 小括号内部的两侧,不要加
36、空格; 大括号内部两侧有无空格,左右必须保持一致; 一元操作符(&*+-!)之后不要加空格; 二元操作符(=+-*/% I & A=!=)左右两侧加空格 三目运算符(?:)符号两侧均需要空格 前置和后置的自增、自减(+-)和变量之间不加空格 结构体成员操作符(.-)前后不加空格 逗号。前面不加空格,后面增加空格 对于模板和类型转换()和类型之间不要添加空格 域操作符(:)前后不要添加空格 冒号(:)前后根据情况来判断是否要添加空格常规情况:void Foo(int b)/ Good:大括号前应该留“X格int i =0;/ Good:变埴初始化时,=前储应该有空格,分心前而不要招个:格int
37、bufkBufSize=0;/ Good:大括号内两侧都无空格函数定义和函数调用:int result = Foo(argl,arg2);A / Bad:逗号后HH需哽增加空格int result = Foo( argl, arg2);A八/ Bad:函数与数列发的左括号后面不应该行个格,右括号前面不应该有空格指针和取地址x =*p;/ Good:*操作符和指针p之间不加空称p=&x;/ Good:&操作符和变献x之间不加安格x =r.y;/ Good:通过.访问成员变吊;时不加空格x = r-y;/ Good:通过-访问成员变量:时不加空格操作符:x =0;/ Good:赋值操作的=前后都要
38、加格x =-5;/ Good:负数的符值之前不要加空格+X;/ Good:的置和后置的+/-和变;1;二之间不要加格 if (x &!y)/Good:布尔操作符前后要加上空格.!操作和变量之间不要空格v = w*x + y/z;/ Good:二元操作符前储要加空格v = w *(x + z);/ Good:括号内的衣达式前后不需要加“。格int a =(x y)? x : y;/ Good:rH运算符,?和:前脑需要添加审格循环和条件语句:if (condition)/ Good: if关键不和括号之间加空格,括号内条件语句前脑不加空格 else / Good: eLse关键字和大括号之间加审
39、格while (condition)/ Good: whiLe关键字和括号之间加格,括号内条件语句前后不加空格for (int i =0; i someRange;+i)/Good: for 关键丁和括号之间加空格.分号之后加空格一switch (condition)/ Good: switch 关犍:后面行1个格case 0:/ Good: case语句条件和H号之间不加个:格break;default:break;)模板和转换/尖括号()不与空格紧邻,和(之间也没有. vector x;y = static_cast(x);/在类型与指针操作符之间留空格也可以,但要保持一致.vector
40、x;域操作符std:cout;/ Good:命i个:问访问,41更:界”。格int MyClass:GetValue() const / Good:寸成员函数定义,不变部、格冒号/添加空格的场景/ Good:类的派生需要留有空格class Sub : public Base ;/构造函数初始化列表需要留有空格MyClass:MyClass(int var): someVar(var) DoSomething();一/位域表示也留有空格struct XX char a :4; char b :5; char c :4;/不添加空格的场景/ Good:对于pubLic:j private:这种类访
41、问权限的冒号不用添加空格class MyClass public:MyClass(int var);private:int someVar;;/对于switch-case的case和def Quit后面的冒号不用添加空格switch (value)case 1:DoSomething();break;default:break;)注意:当前的集成开发环境(IDE)可以设置删除行尾的空格,请正确配置。建议3.14.2合理安排空行,保持代码紧凑减少不必要的空行,可以显示更多的代码,方便代码阅读。下面有一些建议遵守的规则:-根据上下内容的相关程度,合理安排空行;-函数内部、类型定义内部、宏内部、初始
42、化表达式内部,不使用连续空行-不使用连续3个空行,或更多-大括号内的代码块行首之前和行尾之后不要加空行。int Foo()/ Bad:两个函数定义间超过了一个空行 int Bar()if (.)/ Bad:大括号内的代码块行首不要加入空行/ Bad:大括号内的代码块行尾不要加入空行int Foo(.)/ Bad:函数体内行首不要加空行类规则3.15.1类访问控制块的声明依次序是public:, protected:, private:,每个都缩进1个空格class MyClass : public BaseClass public:/注意没有缩进MyClass();/标准的4空格缩进explicit MyClass(int var);MyClass()void SomeFunction();void SomeFunctionThatDoesNothing()一void SetVar(int var) someVar = var;int GetVar() const return someVar;private:bool SomelnternalFunction();int someVar;int someOtherVar;在各个部分中,建议将类似的声明放在一起,并且建议以如下的顺序:类