• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            Creative Commons License
            本Blog采用 知識共享署名-非商業性使用-禁止演繹 3.0 Unported許可協議 進行許可。 —— Fox <游戲人生>

            游戲人生

            游戲人生 != ( 人生 == 游戲 )
            站點遷移至:http://www.yulefox.com。請訂閱本博的朋友將RSS修改為http://feeds.feedburner.com/yulefox
            posts - 62, comments - 508, trackbacks - 0, articles - 7

            [譯]Google C++編程風格指南(七)

            Posted on 2008-07-23 11:43 Fox 閱讀(4390) 評論(7)  編輯 收藏 引用 所屬分類: T技術碎語

            原文地址:

            • 格式

            代碼風格和格式確實比較隨意,但一個項目中所有人遵循同一風格是非常容易的,作為個人未必同意下述格式規則的每一處,但整個項目服從統一的編程風格是很重要的,這樣做才能讓所有人在閱讀和理解代碼時更加容易。

            1. 行長度(Line Length)

            每一行代碼字符數不超過80。

            我們也認識到這條規則是存有爭議的,但如此多的代碼都遵照這一規則,我們感覺一致性更重要。

            優點:提倡該原則的人認為強迫他們調整編輯器窗口大小很野蠻。很多人同時并排開幾個窗口,根本沒有多余空間拓寬某個窗口,人們將窗口最大尺寸加以限定,一致使用80列寬,為什么要改變呢?

            缺點:反對該原則的人則認為更寬的代碼行更易閱讀,80列的限制是上個世紀60年代的大型機的古板缺陷;現代設備具有更寬的顯示屏,很輕松的可以顯示更多代碼。

            結論:80個字符是最大值。例外:

            1) 如果一行注釋包含了超過80字符的命令或URL,出于復制粘貼的方便可以超過80字符;

            2) 包含長路徑的可以超出80列,盡量避免;

            3) 頭文件保護(防止重復包含第一篇)可以無視該原則。

            2. 非ASCII字符(Non-ASCII Characters)

            盡量不使用非ASCII字符,使用時必須使用UTF-8格式。

            哪怕是英文,也不應將用戶界面的文本硬編碼到源代碼中,因此非ASCII字符要少用。特殊情況下可以適當包含此類字符,如,代碼分析外部數據文件時,可以適當硬編碼數據文件中作為分隔符的非ASCII字符串;更常用的是(不需要本地化的)單元測試代碼可能包含非ASCII字符串。此類情況下,應使用UTF-8格式,因為很多工具都可以理解和處理其編碼,十六進制編碼也可以,尤其是在增強可讀性的情況下——如"\xEF\xBB\xBF"是Unicode的zero-width no-break space字符,以UTF-8格式包含在源文件中是不可見的。

            3. 空格還是制表位(Spaces vs. Tabs)

            只使用空格,每次縮進2個空格。

            使用空格進行縮進,不要在代碼中使用tabs,設定編輯器將tab轉為空格。

            譯者注:在前段時間的關于Debian開發學習日記一文中,曾給出針對C/C++編碼使用的vim配置。

            4. 函數聲明與定義(Function Declarations and Definitions)

            返回類型和函數名在同一行,合適的話,參數也放在同一行。

            函數看上去像這樣:

            ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) {
              DoSomething();
              ...
            }
            
            

            如果同一行文本較多,容不下所有參數:

            ReturnType ClassName::ReallyLongFunctionName(Type par_name1,
                                                         Type par_name2,
                                                         Type par_name3) {
              DoSomething();
              ...
            }
            
            

            甚至連第一個參數都放不下:

            ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
                Type par_name1,  // 4 space indent
                Type par_name2,
                Type par_name3) {
              DoSomething();  // 2 space indent
              ...
            }
            
            

            注意以下幾點:

            1) 返回值總是和函數名在同一行;

            2) 左圓括號(open parenthesis)總是和函數名在同一行;

            3) 函數名和左圓括號間沒有空格;

            4) 圓括號與參數間沒有空格;

            5) 左大括號(open curly brace)總在最后一個參數同一行的末尾處;

            6) 右大括號(close curly brace)總是單獨位于函數最后一行;

            7) 右圓括號(close parenthesis)和左大括號間總是有一個空格;

            8) 函數聲明和實現處的所有形參名稱必須保持一致;

            9) 所有形參應盡可能對齊;

            10) 缺省縮進為2個空格;

            11) 獨立封裝的參數保持4個空格的縮進。

            如果函數為const的,關鍵字const應與最后一個參數位于同一行。

            // Everything in this function signature fits on a single line
            ReturnType FunctionName(Type par) const {
              ...
            }
            
            // This function signature requires multiple lines, but
            // the const keyword is on the line with the last parameter.
            ReturnType ReallyLongFunctionName(Type par1,
                                              Type par2) const {
              ...
            }
            
            

            如果有些參數沒有用到,在函數定義處將參數名注釋起來:

            // Always have named parameters in interfaces.
            class Shape {
             public:
              virtual void Rotate(double radians) = 0;
            }
            
            // Always have named parameters in the declaration.
            class Circle : public Shape {
             public:
              virtual void Rotate(double radians);
            }
            
            // Comment out unused named parameters in definitions.
            void Circle::Rotate(double /*radians*/) {}
            // Bad - if someone wants to implement later, it's not clear what the
            // variable means.
            void Circle::Rotate(double) {}
            
            

            譯者注:關于UNIX/Linux風格為什么要把左大括號置于行尾(.cc文件的函數實現處,左大括號位于行首),我的理解是代碼看上去比較簡約,想想行首除了函數體被一對大括號封在一起之外,只有右大括號的代碼看上去確實也舒服;Windows風格將左大括號置于行首的優點是匹配情況一目了然。

            5. 函數調用(Function Calls)

            盡量放在同一行,否則,將實參封裝在圓括號中。

            函數調用遵循如下形式:

            bool retval = DoSomething(argument1, argument2, argument3);
            
            

            如果同一行放不下,可斷為多行,后面每一行都和第一個實參對齊,左圓括號后和右圓括號前不要留空格:

            bool retval = DoSomething(averyveryveryverylongargument1,
                                      argument2, argument3);
            
            

            如果函數參數比較多,可以出于可讀性的考慮每行只放一個參數:

            bool retval = DoSomething(argument1,
                                      argument2,
                                      argument3,
                                      argument4);
            
            

            如果函數名太長,以至于超過行最大長度,可以將所有參數獨立成行:

            if (...) {
              ...
              ...
              if (...) {
                DoSomethingThatRequiresALongFunctionName(
                    very_long_argument1,  // 4 space indent
                    argument2,
                    argument3,
                    argument4);
              }
            
            

            6. 條件語句(Conditionals)

            更提倡不在圓括號中添加空格,關鍵字else另起一行。

            對基本條件語句有兩種可以接受的格式,一種在圓括號和條件之間有空格,一種沒有。

            最常見的是沒有空格的格式,那種都可以,還是一致性為主。如果你是在修改一個文件,參考當前已有格式;如果是寫新的代碼,參考目錄下或項目中其他文件的格式,還在徘徊的話,就不要加空格了。

            if (condition) {  // no spaces inside parentheses
              ...  // 2 space indent.
            } else {  // The else goes on the same line as the closing brace.
              ...
            }
            
            

            如果你傾向于在圓括號內部加空格:

            if ( condition ) {  // spaces inside parentheses - rare
              ...  // 2 space indent.
            } else {  // The else goes on the same line as the closing brace.
              ...
            }
            
            

            注意所有情況下if和左圓括號間有個空格,右圓括號和左大括號(如果使用的話)間也要有個空格:

            if(condition)     // Bad - space missing after IF.
            if (condition){   // Bad - space missing before {.
            if(condition){    // Doubly bad.
            if (condition) {  // Good - proper space after IF and before {.
            
            

            有些條件語句寫在同一行以增強可讀性,只有當語句簡單并且沒有使用else子句時使用:

            if (x == kFoo) return new Foo();
            if (x == kBar) return new Bar();
            
            

            如果語句有else分支是不允許的:

            // Not allowed - IF statement on one line when there is an ELSE clause
            if (x) DoThis();
            else DoThat();
            
            

            通常,單行語句不需要使用大括號,如果你喜歡也無可厚非,也有人要求if必須使用大括號:

            if (condition)
              DoSomething();  // 2 space indent.
            
            if (condition) {
              DoSomething();  // 2 space indent.
            }
            
            

            但如果語句中哪一分支使用了大括號的話,其他部分也必須使用:

            // Not allowed - curly on IF but not ELSE
            if (condition) {
              foo;
            } else
              bar;
            
            // Not allowed - curly on ELSE but not IF
            if (condition)
              foo;
            else {
              bar;
            }
             
            // Curly braces around both IF and ELSE required because
            // one of the clauses used braces.
            if (condition) {
              foo;
            } else {
              bar;
            }
            
            

            7. 循環和開關選擇語句(Loops and Switch Statements)

            switch語句可以使用大括號分塊;空循環體應使用{}continue

            switch語句中的case塊可以使用大括號也可以不用,取決于你的喜好,使用時要依下文所述。

            如果有不滿足case枚舉條件的值,要總是包含一個default(如果有輸入值沒有case去處理,編譯器將報警)。如果default永不會執行,可以簡單的使用assert

            switch (var) {
              case 0: {  // 2 space indent
                ...      // 4 space indent
                break;
              }
              case 1: {
                ...
                break;
              }
              default: {
                assert(false);
              }
            }
            
            

            空循環體應使用{}continue,而不是一個簡單的分號:

            while (condition) {
              // Repeat test until it returns false.
            }
            for (int i = 0; i < kSomeNumber; ++i) {}  // Good - empty body.
            while (condition) continue;  // Good - continue indicates no logic.
            while (condition);  // Bad - looks like part of do/while loop.
            
            

            8. 指針和引用表達式(Pointers and Reference Expressions)

            句點(.)或箭頭(->)前后不要有空格,指針/地址操作符(*、&)后不要有空格。

            下面是指針和引用表達式的正確范例:

            x = *p;
            p = &x;
            x = r.y;
            x = r->y;
            
            

            注意:

            1) 在訪問成員時,句點或箭頭前后沒有空格;

            2) 指針操作符*&后沒有空格。

            在聲明指針變量或參數時,星號與類型或變量名緊挨都可以:

            // These are fine, space preceding.
            char *c;
            const string &str;
            
            // These are fine, space following.
            char* c;    // but remember to do "char* c, *d, *e, ...;"!
            const string& str;
            char * c;  // Bad - spaces on both sides of *
            const string & str;  // Bad - spaces on both sides of &
            
            

            同一個文件(新建或現有)中起碼要保持一致。

            譯者注:個人比較習慣與變量緊挨的方式

            9. 布爾表達式(Boolean Expressions)

            如果一個布爾表達式超過標準行寬(80字符),如果斷行要統一一下。

            下例中,邏輯與(&&)操作符總位于行尾:

            if (this_one_thing > this_other_thing &&
                a_third_thing == a_fourth_thing &&
                yet_another & last_one) {
              ...
            }
            
            

            兩個邏輯與(&&)操作符都位于行尾,可以考慮額外插入圓括號,合理使用的話對增強可讀性是很有幫助的。

            譯者注:個人比較習慣邏輯運算符位于行首,邏輯關系一目了然,各人喜好而已,至于加不加圓括號的問題,如果你對優先級了然于胸的話可以不加,但可讀性總是差了些。

            10. 函數返回值(Return Values)

            return表達式中不要使用圓括號。

            函數返回時不要使用圓括號:

            return x;  // not return(x);
            
            

            11. 變量及數組初始化(Variable and Array Initialization)

            選擇=還是()。

            需要做二者之間做出選擇,下面的形式都是正確的:

            int x = 3;
            int x(3);
            string name("Some Name");
            string name = "Some Name";
            
            

            12. 預處理指令(Preprocessor Directives)

            預處理指令不要縮進,從行首開始。

            即使預處理指令位于縮進代碼塊中,指令也應從行首開始。

            // Good - directives at beginning of line
              if (lopsided_score) {
            #if DISASTER_PENDING      // Correct -- Starts at beginning of line
                DropEverything();
            #endif
                BackToNormal();
              }
            // Bad - indented directives
              if (lopsided_score) {
                #if DISASTER_PENDING  // Wrong!  The "#if" should be at beginning of line
                DropEverything();
                #endif                // Wrong!  Do not indent "#endif"
                BackToNormal();
              }
            
            

            13. 類格式(Class Format)

            聲明屬性依次序是public:protected:private:,每次縮進1個空格(譯者注,為什么不是兩個呢?也有人提倡private在前,對于聲明了哪些數據成員一目了然,還有人提倡依邏輯關系將變量與操作放在一起,都有道理:-)。

            類聲明(對類注釋不了解的話,參考第六篇中的類注釋一節)的基本格式如下:

            class MyClass : public OtherClass {
             public:      // Note the 1 space indent!
              MyClass();  // Regular 2 space indent.
              explicit MyClass(int var);
              ~MyClass() {}
            
              void SomeFunction();
              void SomeFunctionThatDoesNothing() {
              }
            
              void set_some_var(int var) { some_var_ = var; }
              int some_var() const { return some_var_; }
            
             private:
              bool SomeInternalFunction();
            
              int some_var_;
              int some_other_var_;
              DISALLOW_COPY_AND_ASSIGN(MyClass);
            };
            
            

            注意:

            1) 所以基類名應在80列限制下盡量與子類名放在同一行;

            2) 關鍵詞public:、protected:、private:要縮進1個空格(譯者注,MSVC多使用tab縮進,且這三個關鍵詞沒有縮進)

            3) 除第一個關鍵詞(一般是public)外,其他關鍵詞前空一行,如果類比較小的話也可以不空;

            4) 這些關鍵詞后不要空行;

            5) public放在最前面,然后是protectedprivate

            6) 關于聲明次序參考第三篇聲明次序一節。

            14. 初始化列表(Initializer Lists)

            構造函數初始化列表放在同一行或按四格縮進并排幾行。

            兩種可以接受的初始化列表格式:

            // When it all fits on one line:
            MyClass::MyClass(int var) : some_var_(var), some_other_var_(var + 1) {
            
            

            // When it requires multiple lines, indent 4 spaces, putting the colon on
            // the first initializer line:
            MyClass::MyClass(int var)
                : some_var_(var),             // 4 space indent
                  some_other_var_(var + 1) {  // lined up
              ...
              DoSomething();
              ...
            }
            
            

            15. 命名空間格式化(Namespace Formatting)

            命名空間內容不縮進。

            命名空間不添加額外縮進層次,例如:

            namespace {
            
            void foo() {  // Correct.  No extra indentation within namespace.
              ...
            }
            
            }  // namespace
            
            

            不要縮進:

            namespace {
            
              // Wrong.  Indented when it should not be.
              void foo() {
                ...
              }
            
            }  // namespace
            
            

            16. 水平留白(Horizontal Whitespace)

            水平留白的使用因地制宜。不要在行尾添加無謂的留白。

            普通

            void f(bool b) {  // Open braces should always have a space before them.
              ...
            int i = 0;  // Semicolons usually have no space before them.
            int x[] = { 0 };  // Spaces inside braces for array initialization are
            int x[] = {0};    // optional.  If you use them, put them on both sides!
            // Spaces around the colon in inheritance and initializer lists.
            class Foo : public Bar {
             public:
              // For inline function implementations, put spaces between the braces
              // and the implementation itself.
              Foo(int b) : Bar(), baz_(b) {}  // No spaces inside empty braces.
              void Reset() { baz_ = 0; }  // Spaces separating braces from implementation.
              ...
            
            

            添加冗余的留白會給其他人編輯時造成額外負擔,因此,不要加入多余的空格。如果確定一行代碼已經修改完畢,將多余的空格去掉;或者在專門清理空格時去掉(確信沒有其他人在使用)。

            循環和條件語句

            if (b) {          // Space after the keyword in conditions and loops.
            } else {          // Spaces around else.
            }
            while (test) {}   // There is usually no space inside parentheses.
            switch (i) {
            for (int i = 0; i < 5; ++i) {
            switch ( i ) {    // Loops and conditions may have spaces inside
            if ( test ) {     // parentheses, but this is rare.  Be consistent.
            for ( int i = 0; i < 5; ++i ) {
            for ( ; i < 5 ; ++i) {  // For loops always have a space after the
              ...                   // semicolon, and may have a space before the
                                    // semicolon.
            switch (i) {
              case 1:         // No space before colon in a switch case.
                ...
              case 2: break;  // Use a space after a colon if there's code after it.
            
            

            操作符

            x = 0;              // Assignment operators always have spaces around
                                // them.
            x = -5;             // No spaces separating unary operators and their
            ++x;                // arguments.
            if (x && !y)
              ...
            v = w * x + y / z;  // Binary operators usually have spaces around them,
            v = w*x + y/z;      // but it's okay to remove spaces around factors.
            v = w * (x + z);    // Parentheses should have no spaces inside them.
            
            

            模板和轉換

            vector<string> x;           // No spaces inside the angle
            y = static_cast<char*>(x);  // brackets (< and >), before
                                        // <, or between >( in a cast.
            vector<char *> x;           // Spaces between type and pointer are
                                        // okay, but be consistent.
            set<list<string> > x;       // C++ requires a space in > >.
            set< list<string> > x;      // You may optionally make use
                                        // symmetric spacing in < <.
            
            

            17. 垂直留白(Vertical Whitespace)

            垂直留白越少越好。

            這不僅僅是規則而是原則問題了:不是非常有必要的話就不要使用空行。尤其是:不要在兩個函數定義之間空超過2行,函數體頭、尾不要有空行,函數體中也不要隨意添加空行。

            基本原則是:同一屏可以顯示越多的代碼,程序的控制流就越容易理解。當然,過于密集的代碼塊和過于疏松的代碼塊同樣難看,取決于你的判斷,但通常是越少越好。

            函數頭、尾不要有空行:

            void Function() {
            
              // Unnecessary blank lines before and after
            
            }
            
            

            代碼塊頭、尾不要有空行:

            while (condition) {
              // Unnecessary blank line after
            
            }
            if (condition) {
            
              // Unnecessary blank line before
            }
            
            

            if-else塊之間空一行還可以接受:

            if (condition) {
              // Some lines of code too small to move to another function,
              // followed by a blank line.
            
            } else {
              // Another block of code
            }
            
            

            ______________________________________

            譯者:首先說明,對于代碼格式,因人、因系統各有優缺點,但同一個項目中遵循同一標準還是有必要的:

            1. 行寬原則上不超過80列,把22寸的顯示屏都占完,怎么也說不過去;

            2. 盡量不使用非ASCII字符,如果使用的話,參考UTF-8格式(尤其是UNIX/Linux下,Windows下可以考慮寬字符),盡量不將字符串常量耦合到代碼中,比如獨立出資源文件,這不僅僅是風格問題了;

            3. UNIX/Linux下無條件使用空格,MSVC的話使用Tab也無可厚非;

            4. 函數參數、邏輯條件、初始化列表:要么所有參數和函數名放在同一行,要么所有參數并排分行;

            5. 除函數定義的左大括號可以置于行首外,包括函數/類/結構體/枚舉聲明、各種語句的左大括號置于行尾,所有右大括號獨立成行;

            6. ./->操作符前后不留空格,*/&不要前后都留,一個就可,靠左靠右依各人喜好;

            7. 預處理指令/命名空間不使用額外縮進,類/結構體/枚舉/函數/語句使用縮進;

            8. 初始化用=還是()依個人喜好,統一就好;

            9. return不要加();

            10. 水平/垂直留白不要濫用,怎么易讀怎么來。

            Feedback

            # re: [譯]Google C++編程風格指南(七)  回復  更多評論   

            2008-07-25 10:07 by tangfl
            4) 圓括號與參數間沒有看過; ???

            # re: [譯]Google C++編程風格指南(七)  回復  更多評論   

            2008-07-25 14:27 by Fox
            空格,呵呵,謝謝提醒!:D

            # re: [譯]Google C++編程風格指南(七)  回復  更多評論   

            2010-07-18 04:13 by AvilaNoelle22
            It's good that we can get the <a href="http://bestfinance-blog.com/topics/home-loans">home loans</a> moreover, it opens up completely new possibilities.

            # re: [譯]Google C++編程風格指南(七)  回復  更多評論   

            2010-08-02 02:48 by annotated bibliography
            That's not easy to deal with several things at the same time, especially when you have to create the essay papers. The only purchase essays service would manage even with complicated tasks.
            久久中文字幕精品| 国产女人aaa级久久久级| 性做久久久久久久| 精品久久久久久久| 亚洲成av人片不卡无码久久| 久久精品免费一区二区| 国产亚洲美女精品久久久| 久久精品国产亚洲av麻豆图片| 久久国产精品-久久精品| 中文字幕无码久久人妻| 99久久久久| 99久久精品费精品国产一区二区| 久久久久香蕉视频| 久久最近最新中文字幕大全 | 久久精品中文无码资源站| 国产精品热久久无码av| 久久国产欧美日韩精品 | 亚洲伊人久久综合中文成人网| 久久午夜无码鲁丝片| 日批日出水久久亚洲精品tv| 亚洲狠狠综合久久| www.久久99| 97久久精品无码一区二区| 色婷婷综合久久久中文字幕 | 国产精品日韩欧美久久综合| 久久国产精品久久精品国产| 久久精品国产亚洲AV嫖农村妇女| 97精品依人久久久大香线蕉97| 中文精品99久久国产| 国内精品久久久久影院亚洲| 久久综合色区| 亚洲欧洲精品成人久久奇米网| 久久久久亚洲AV成人网| 久久久久无码中| 亚洲国产精品嫩草影院久久| 久久天天躁狠狠躁夜夜2020| 思思久久99热免费精品6| 亚洲国产成人久久笫一页| 亚洲精品tv久久久久久久久久| 伊人久久成人成综合网222| 欧美国产成人久久精品|