世界上有很多问题, Z知道如何去解?但是, gq还不算是最高明?更高明的做法是学会避免问题的发生.而如何避免问题的发生, 需要经验的U篏--曄犯下错误,吃一堑长一?于是知道哪些事情是不该做的或者是不应该这么做?
google C++ code style是google对外公布的一份google内部~写C++的代码规范文?与其他很多我曄看过的编码文一?里面有一些关于代码风格的规定,也就是代码的外观,q一部分不在q里q多讨论,毕竟代码如何才叫"观"是一个见仁见智的话题.在这里专门讨份文档中对一些C++Ҏ该如何使用的讨?最后再做一个ȝ.注意其中的序号ƈ不是文中的序号,如果要详l了?可以自己ȝq䆾文.
1) Static and Global Variables
Static or global variables of class type are forbidden: they cause hard-to-find bugs due to indeterminate order of construction and destruction.
google明确止全局对象是类对象, 只能是所谓POD(Plain Old Data,如int char{?数据才行.因ؓC++标准中没有明规定全局对象的初始化序, 假设全局cd象A,B,其中A的初始化依赖于B的? 那么无法保证最后的l果.如果非要使用全局cd? 那么只能使用指针, 在main{函数入口统一q行初始?
2) Doing Work in Constructors
In general, constructors should merely set member variables to their initial values. Any complex initialization should go in an explicit Init() method.
文规定, 在类构造函C对类成员对象做基本的初始化操? 所有的复杂初始化操作集中一个比如Init()的函C,理由如下:
- There is no easy way for constructors to signal errors,
short of using exceptions (which are
forbidden).
- If the work fails, we now have an object whose
initialization code failed, so it may be an
indeterminate state.
- If the work calls virtual functions, these calls will
not get dispatched to the subclass implementations.
Future modification to your class can quietly introduce
this problem even if your class is not currently
subclassed, causing much confusion.
- If someone creates a global variable of this type
(which is against the rules, but still), the
constructor code will be called before
main()
, possibly breaking some implicit
assumptions in the constructor code. For instance,
gflags
will not yet have been initialized.
单的概括h也就?构造函数没有返回? 难以让用者感知错?假如在构造函C调用虚拟函数, 则无法按照用者的x调用到对应子cM实现的虚拟函?理由是构造函数还未完成意味着q个对象q没有被成功构造完?.
3) Default Constructors
You must define a default constructor if your class defines member variables and has no other constructors. Otherwise the compiler will do it for you, badly.
当程序员没有为类~写一个默认构造函数的时? ~译器会自动生成一个默认构造函?而这个编译器生成的函数如何实?比如如何初始化类成员对象)是不定?q样,假如出现问题时将l调试跟t带来困?所? 规范要求每个c都需要编写一个默认构造函数避免这U情늚出现.
4) Explicit Constructors
Use the C++ keyword explicit for constructors with one argument.
假如构造函数只有一个参? 使用explicit避免隐式转换,
因ؓ隐式转换可能在你q不需要的时候出?
5) Copy Constructors
Provide a copy constructor and assignment operator only when necessary. Otherwise, disable them with DISALLOW_COPY_AND_ASSIGN.
只有当必要的时候才需要定义拷贝构造函数和赋值操作符.
同上一条理׃? 避免一些隐式的转换.另一条理由是,"="难以跟踪,如果真的要实现类似的功能,可以提供比如名ؓCopy()的函?q样子一目了?不会像赋值操作符那样可能在每?="出现的地方出?
6) Operator Overloading
Do not overload operators except in rare, special circumstances.
不要重蝲操作W?同样, 也是避免莫名其妙的调用了一些函?同上一条一? 比如要提供对"=="的重? 可以提供一个名为Equal()的函? 如果需要提供对"+"的重? 可以提供一个名为Add()的函?
7) Function Overloading
Use overloaded functions (including constructors) only in cases where input can be specified in different types that contain the same information. Do not use function overloading to simulate default function parameters.
只有在不同的cd表示同样的信息的时? 可以使用重蝲函数.其他情况?一律不能?使用重蝲, 也可能出C些隐式出现的转换.所? 在需要对不同函数q行同样操作的时? 可以在函数名UCq行区分, 而不是用重?如可以提供针对stringcd的AppendString()函数, 针对intcd的AppendInt()函数,而不是对string和intcd重蝲Append()函数.另一个好处在? 在阅M码时,通过函数名称可以一目了?
8) Exceptions
We do not use C++ exceptions.
不用异?理由如下:
- When you add a
throw
statement to an existing
function, you must examine all of its transitive callers.
Either
they must make at least the basic exception safety guarantee,
or
they must never catch the exception and be happy with the
program terminating as a result. For instance, if
f()
calls g()
calls
h()
, and h
throws an exception
that f
catches, g
has to be
careful or it may not clean up properly.
- More generally, exceptions make the control flow of
programs difficult to evaluate by looking at code: functions
may return in places you don't expect. This results
maintainability and debugging difficulties. You can minimize
this cost via some rules on how and where exceptions can be
used, but at the cost of more that a developer needs to know
and understand.
- Exception safety requires both RAII and different coding
practices. Lots of supporting machinery is needed to make
writing correct exception-safe code easy. Further, to avoid
requiring readers to understand the entire call graph,
exception-safe code must isolate logic that writes to
persistent state into a "commit" phase. This will have both
benefits and costs (perhaps where you're forced to obfuscate
code to isolate the commit). Allowing exceptions would force
us to always pay those costs even when they're not worth
it.
- Turning on exceptions adds data to each binary produced,
increasing compile time (probably slightly) and possibly
increasing address space pressure.
- The availability of exceptions may encourage developers
to throw them when they are not appropriate or recover from
them when it's not safe to do so. For example, invalid user
input should not cause exceptions to be thrown. We would
need to make the style guide even longer to document these
restrictions!
上面提到的理׃, 我认Z用异常最大的宛_是:异常的用导致了E序无法按照代码所展现的流E去走的, 比如代码里面写了步骤一二三,但是假如有异常出? q就不好预知代码真正步进的步骤了, 在出现问题时, l调试和跟踪带来困难.
另外, 我更喜欢unix API的设?熟悉unix~程的h都知? unix API基本上都遵守下列规则:
a) q回0表示成功, 其他(一般是-1)表示p|.
b) 在失败时, 可以Ҏerrno判断p|的原? q些在man手册中都是会清楚的描q?
ȝ一? q䆾规范中规避的C++Ҏ大致分Z下几c?
a) 避免使用那些没有定行ؓ的特?如全局变量不能是类对象(初始化顺序不定), 不用编译器生成的默认构造函?构造行Z定), 异常(代码走向不确?.
b) 避免使用那些隐式发生的操?如声明单参数构造函Cؓexplict以避免隐式{? 不定义拷贝构造函数避免隐式的拯行ؓ, 不用操作符重蝲避免隐式的{?br>c) Ҏ׃可的Ҏ给予明的规定:不用函数重载而是定义Ҏ个类型明的函数.
d) 即出错了程序也有办法知? 比如不能在类构造函Cq行复杂的构造操? 这些移动到cInit()的函C.
同时, q䆾文档中描q的大部分C++Ҏ? 都是我之前所熟悉?除了RTTI之外, 不过q里提到它也是要说明不用它,另外q提到boost, 不过也是说的要对?有限?的?比如里面的智能指?.可以看到, 面对q样一门复杂同时还在不停的发展更新Ҏ的语言, google的态度是比?保守"?q与我之前对C++的理解也是接q的, 我一直认为C++中需要用到的特性有基本的面向对?STL够?l过最q的~码实践,我认得加个智能指?.我对q个"保守"态度的理解是, 以C++当前的应用场景来? q些Ҏ已l? 如果使用其他一些更加复杂的, 对h的要求提高了, 代码的可L以及以后的可维护性就下降?
前面说过, 避免问题的出现比解决问题来的更加高明? 而面对C++q一个提供了众多Ҏ? google C++ code stylel予了明的规定, 也就是每个行? 如果都能做到有明的动作, 同时l果也都是可以预知的, 那么会将出问题的概率最大可能的降低, 即Z问题, 也容易跟t?
上面描述的ƈ不是q䆾文中有关C++的所有内? 只不q我觉得q些更加有同感些, 详细的内? 可以参看q䆾文.都知道google的作?质量有保? 除了人的素质实高之? 有规范的制度保证也是重要的原? 毕竟只要是h׃犯错, Z最大限度的避免人犯? 有一份详的代码规范, 写好哪些该做哪些不该做哪些不该这么做, 也是制度上的保证.另外, 假如每个人都能以一个比较高的标准要求自己所写的代码, 久而久? 获得q步也是必然的结?
从这套规范里? 我的另一个感悟是, 不论是什么行? "学会如何正确的做事情", 都是十分必要?q个"正确的做事情", 具体到编码来? 是代码规范里面提到的那些要?而除ȝ? 做Q何的事情, 使用正确的方式做? 都是可能少的避免错误的Ҏ.但是, "???是相对而言? 没有之前"?的经? ׃好体会什么叫"?.所? "如何正确的做?, 说到了最? q得看个人的l验U篏, 有了之前"错误"的经?才能吃一堑长一? "错误"q不是一无是处的, 只不q? q不是谁都去试着从中学习.

]]>