Google C++スタイルガイド日本語訳
- お知らせ
- この訳について
- Google C++スタイルガイド
- 背景
- ヘッダファイル
- スコープ
- クラス
- コンストラクタ内での作業
- デフォルトコンストラクタ
- 明示的なコンストラクタ
- コピーコンストラクタ
- 構造体 vs. クラス
- 継承
- 多重継承
- インターフェース
- 演算子オーバーロード
- アクセス管理
- 宣言の順序
- 短い関数を書け
- グーグル固有のマジック
- その他のC++の機能
- 参照引数
- 関数オーバーロード
- デフォルト引数
- 可変長配列とalloca()
- フレンド
- 例外
- 実行時型情報(RTTI)
- キャスト
- ストリーム
- 前置インクリメント/デクリメント
- constの使用
- 整数型
- 64ビットへの可搬性
- プリプロセッサマクロ
- 0とNULL
- sizeof
- Boost
- 名前付け
- コメント
- フォーマット
- 行の長さ
- 非ASCII文字
- スペース vs. タブ
- 関数の宣言と定義
- 関数の呼び出し
- 条件文
- ループとswitch文
- ポインタと参照
- ブーリアン表現
- 戻り値
- 変数・配列の初期化
- プリプロセッサ命令
- クラスのフォーマット
- 初期化子リスト
- 名前空間のフォーマット
- 水平方向の空白
- 垂直方向の空白
- 規則の例外
- おわりに
- フィードバック
お知らせ
textdropさんが全訳(http://www.textdrop.net/google-styleguide-ja/cppguide.xml)を公開されました。(2008年12月21日)
この訳について
この日本語訳はhttp://google-styleguide.googlecode.com/svn/trunk/cppguide.xmlのrevision8から作成されたものです。
原版では各項目に詳細がありますが、本訳では明記されていない場合は省略されています。 この訳はGoogleとはまったく関係がなく、内容の正確さはいっさい保証されません。この訳は権利者から許可を得て行ったものではなく、正当な権利者から申し立てがあった場合は予告なく削除されます。
この訳の改変・追記・複製・再配布は自由に行って下さい。誰もがこれらの行為を事前・事後の通告なく行うことができます。この訳のライセンスは原版のプロジェクトにならいArtistic License/GPLv2とします。(2008年7月2日修正)
このページのhiki記法でのテキストはこちらのリンクからご覧になれます。
変更履歴
- 2008年6月30日:初出
- 2008年7月3日:元のrevisionを3から4に変更。「Boost」の項を更新
- 2008年7月14日:「例外」「実行時型情報(RTTI)」の項に詳細を追加
- 2008年9月9日:元のrevisionを8に変更。「Boost」の項を更新
Google C++スタイルガイド
Benjy Weinberger
Craig Silverstein
Gregory Eitzmann
Mark Mentovai
Tashana Landray
背景
C++はグーグルの多くのオープンソースプロジェクトの開発用言語です。C++プログラマの多くが知っているように、C++は多くの強力な機能を備えています。しかし同時にこの力はときにバグりがちで読みづらく保守しにくい複雑さをコードに与えてしまいます。
このガイドの目標はC++コードを書く上でのべし/べからずを詳細に表すことで、この複雑さを管理することにあります。コードを書くときにC++の機能を生産的に使うことを許しながらコードベースを管理可能にするために、これらの規則は存在しているのです。
スタイル、もしくは可読性とは、いうなればC++コードを管理するための決まりのことです。これらの決まりはソースファイルのフォーマット以外の事柄にも及んでいるので、"スタイル"という言葉には若干の語弊があります。
コードベースを管理可能にしておく方法のひとつに、一貫性の強制があります。どんなプログラマでも他人のコードを見てすぐに理解できるというのはとても重要なことです。同じスタイルを貫き決まりに従っていれば、たくさんの識別子が何なのか、またそれらについてどの不変条件が真なのかを推測するのに"パターンマッチング"をより簡単に使うことができるようになります。必要なイディオムやパターンに共通なものを用意しておくことで、コードはより理解しやすくなります。場合によってはある規則を変更すべき十分な理由が存在するかもしれません、しかし我々は一貫性を保つためにそれでも変更は行いません。
このガイドは更にC++の肥大した機能についても扱います。C++は多くの先進的な機能を持った巨大な言語です。我々は場合によっては特定の機能の使用を制限、もしくは禁止します。我々はコードを明快にし、これらの機能が引き起こす多くのエラーや問題を回避するためにこれを行います。このガイドはそのような機能を列記し、なぜ制限されたのかを説明します。
グーグルにより開発されたオープンソースプロジェクトはこのガイドの要求に従います。
このガイドはC++チュートリアルではないことに注意してください、読者はすでにC++に習熟していると想定されています。
ヘッダファイル
一般に、全ての .ccファイルは関連付けられた .hファイルを持つべきです。ユニットテストやmain()関数を含む小さな .ccファイルなど、いくつかの例外はあります。
ヘッダファイルを正しく利用することで、コードの可読性・サイズ・性能に大きな違いが生まれます。
以下の規則はヘッダファイルを使う上でのたくさんの罠の案内になるでしょう。
インクルードガード
全てのヘッダファイルは多重インクルードを避けるために#defineガードを持つべきです。識別子名のフォーマットは<プロジェクト名>_<パス>_<ファイル名>_H_とするべきです。
詳細
一意性を保証するために、フォーマットはソースツリー内の完全なパスに基づくべきです。例えば、fooというプロジェクトの"foo/src/bar/baz.h"というファイルは以下のようなインクルードガードを持つべきです
#ifndef FOO_BAR_BAZ_H_ #define FOO_BAR_BAZ_H_ ... #endif // FOO_BAR_BAZ_H_
ヘッダ依存関係
先行宣言を使って .hファイル内での#includeは最小限に留めてください。
インライン関数
関数は小さい場合(10行以下)に限りインライン定義してください。
"-inl.h"ファイル
必要な場合、"-inl.h"という接尾辞を持ったファイルを使って複雑なインライン関数を定義することができます。
関数の引数の順番
関数を定義するときパラメータの順番は入力、出力の順です。
名前およびインクルードの順番
可読性と隠れた依存関係を避けるために、順番は標準に従ってください:Cライブラリ、C++ライブラリ、その他のライブラリの .h、あなたのプロジェクトの .h。
スコープ
名前空間
.ccファイル内での無名名前空間の使用は推奨されます。名前のある名前空間については、プロジェクト名に基づき、可能ならパスに基づいた名前を選んでください。using指定子は使わないでください。
ネストされたクラス
インターフェースの一部である場合にはpublicなネストされたクラスを使用することができますが、グローバルスコープに宣言を置かない目的には名前空間を使用してください。
非メンバ・静的メンバ・グローバル関数
グローバル関数よりも名前空間内の非メンバ関数や静的メンバ関数が望ましい。グローバル関数はめったに使わないでください。
ローカル変数
関数の変数は可能な限り狭いスコープに入れて、宣言と同時に初期化してください。
グローバル変数
クラス型のグローバル変数は禁止します。組み込み型のグローバル変数は許可しますが、非constのグローバル変数はスレッドを使うコードでは禁止します。グローバル変数を関数の戻り値で初期化してはいけません。
クラス
クラスはC++でのコードの基本単位です。当然、我々はクラスを広範囲に利用しています。この項ではクラスを書くときに従うべき"べし/べからず"を列記します。
コンストラクタ内での作業
コンストラクタ内では些細な初期化のみ行ってください。可能であれば、必要な初期化のためにはInit()メソッドを使用してください。
デフォルトコンストラクタ
クラスがメンバ変数を持ちその他のコンストラクタを持たないなら、デフォルトコンストラクタを定義しなければなりません。そうしないと、コンストラクタがあなたの代わりにまずい方法でやってしまいます。
明示的なコンストラクタ
1変数を受け取るコンストラクタにはexplicitキーワードを使用してください。
コピーコンストラクタ
あなたのコードがクラスをコピーする必要があるときにだけコピーコンストラクタを使ってください。ほとんどの場合コピーの必要はないので、DISALLOW_COPY_AND_ASSIGNを利用するべきです。
詳細(抜粋)
便利のために、DISALLOW_COPY_AND_ASSIGNマクロを使用できます。
// A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&)
そして、class Foo; の中で
class Foo {
public:
Foo(int f);
~Foo();
private:
DISALLOW_COPY_AND_ASSIGN(Foo);
};
構造体 vs. クラス
structはデータを運ぶだけの受け身のオブジェクトに対してのみ使用してください。他は全部classです。
継承
多くの場合、合成(composition)は継承よりも適切です。継承を使うときはpublicにしてください。
多重継承
実装の多重継承が本当に有効なことは大変まれです。実装を持つのが基底クラスのうち1つ以下である場合に限り多重継承は許可されます。その他の基底クラスはInterface接尾辞のついた純粋インターフェースクラスでなければいけません。
インターフェース
いくつかの条件を満たしたクラスはInterface接尾辞をつけることが許されます、必ずつけなければならないわけではありません。
詳細(抜粋)
定義
以下の条件を満たすクラスが純粋インターフェースです
- publicな純粋仮想("=0")メソッドと静的メソッドのみ持つ(デストラクタについては下記を見てください)
- 非静的データメンバを持たない
- いかなるコンストラクタも定義されている必要はない。コンストラクタが提供される場合、引数をとらずprotectedでなければならない。
- サブクラスである場合、基底クラスはこれらの条件を満たしInterface接尾辞がついたクラスでなければならない。
インターフェースクラスは純粋仮想メソッドしか宣言していないので直接インスタンスが作られることはありません。あらゆるインターフェースの実装が正しく破棄されるために、仮想デストラクタ(1番目の条件に対する例外として、これは純粋仮想であるべきではありません)を宣言しなければなりません。詳細については「プログラミング言語C++ 第3版」の12.4を見てください。
演算子オーバーロード
まれで特別な状況を除いて演算子をオーバーロードしてはいけません。
詳細(抜粋)
一般に演算子をオーバーロードしてはいけません。代入演算子(operator=)は特に油断がならないので避けられるべきです。必要ならEquals()やCopyFrom()のような関数を定義できます。
しかし、まれにテンプレートや"標準"C++クラスとやり取りするために(例えばログを取るためのoperator<<(ostream&, const T&))演算子をオーバーロードする必要が生じる場合があります。完全に合理的な場合は受け入れられますが、可能な限り避けようとするべきです。特に、あなたのクラスがSTLコンテナのキーとして使えるようにoperator==やoperator<をオーバーロードしてはいけません。代わりに、コンテナを宣言するときに等価・比較ファンクタ型を作るべきです。
いくつかのSTLのアルゴリズムはoperator==のオーバーロードを要求するのでこれは許可されますが、あなたはドキュメントに理由を記さなければいけません。
「コピーコンストラクタ」と「関数オーバーロード」の項も見てください。
アクセス管理
全てのデータメンバはprivateにし、必要ならアクセサ関数を定義してください。一般に変数名が foo_ ならアクセサ関数は foo()です。値を変更するための関数(mutator)であるset_foo()は許可されます。
宣言の順序
クラス内では指定された順序で宣言を行ってください:public:が先でprivate:が後、メソッドが先でデータメンバ(変数)が後、etc.
詳細
クラス定義はpublic:節から始まり、protected:節が続き、その後にprivate:節があるべきです。3つの節のうちどれでも空白のものがあれば、省略してください。
それぞれの節の中では、宣言は一般に下記の順序に従うべきです。
- typedef および enum
- 定数
- コンストラクタ
- メソッド(静的メソッドを含む)
- データメンバ(静的データメンバを含む)
DISALLOW_COPY_AND_ASSIGNマクロはprivate:節の終わりに置かれ、クラスの最後の要素になるべきです。「コピーコンストラクタ」の項を見てください。
対応する .ccファイルでのメソッド定義は可能な限り宣言と同じ順序で行われるべきです。
大きなメソッドをクラス定義内でインライン定義してはいけません。ふつう、些細であったり性能上重要であり、とても短いメソッドがインライン定義を許されます。詳細は「インライン関数」の項を見てください。
短い関数を書け
関数は小さくて狙いが定まっていることが望ましいです。
グーグル固有のマジック
C++コードをより堅牢にするためのたくさんのトリックや道具、あなたが他の場所で見てきたのとは違うかもしれないたくさんのC++の使い方があります。
スマートポインタ
ポインタのセマンティクスが必要なら、scoped_ptrという素晴らしい方法があります。std::tr1::shared_ptrは、オブジェクトがSTLコンテナに保有される必要がある場合などのかなり特定された状況に限って使用するべきです。auto_ptrは使用するべきではありません。
その他のC++の機能
参照引数
参照で渡される引数は全てconstでなければいけません。
関数オーバーロード
関数オーバーロード(コンストラクタを含む)は、同じ情報を持つ入力が違う型で表せる場合に限り使用してください。デフォルト引数と同じことをするために関数オーバーロードを使用しないでください。
デフォルト引数
デフォルト引数は許可されません。
可変長配列とalloca()
可変長配列やalloca()は許可されません。
フレンド
friendクラスおよび関数の利用は、理由があれば許可されます。
詳細
読む人がクラスのprivateメンバが利用されている様子を他のファイルまで見に行かなくてすむよう、フレンドは同じファイル内で定義されるべきです。friendのよくある利用としては、Fooが外部に対して内部状態を晒さないままでFooの内部状態を正しく構築できるように、FooBuilderクラスがFooのフレンドになるというものがあります。場合によっては、ユニットテストクラスがテストするクラスのフレンドになるのも有用でしょう。
フレンドはクラスのカプセル化境界を拡大しますが破壊はしません。ただ一つのクラスに対してアクセスを許したいときは、メンバをpublicにするより優れている場合もあります。ですが、ほとんどのクラスは他のクラスとpublicメンバを通じてのみ作用しあうべきです。
例外
我々はC++例外を使用しません。
詳細(抜粋)
特に新しいプロジェクトにおいて、例外を使用することで得られる利益は表面上必要となる労力を上回ります。しかし、既存のコードに対して例外を導入すれば、全ての依存するコードへも影響を与えてしまいます。もし例外が新しいプロジェクトの外にまで伝播されうるのであれば、例外を使わない既存のコードにその新しいプロジェクトを統合する作業は難しいものとなるでしょう。グーグルの既存のC++コードが例外に対応するようにできていないので、例外を発生させる新しいコードを受け入れるのはとても難しいのです。
グーグルの既存のコードが例外に対して耐性がないので、まったく新しいプロジェクトで使用する場合に比べて例外の使用に若干大きな労力を必要とします。変換の作業は遅く間違いの温床となることでしょう。エラーコードやアサーションのような例外の代替手段が著しい重荷になるとも考えられません。
例外の使用に反対する我々の意見は、哲学や教訓ではなく、実践に基づいたものです。我々は自分たちのオープンソースプロジェクトをグーグルで使用したいですし、それらのプロジェクトが例外を使用しているとその使用が難しくなってしまう以上は、グーグルのオープンソースプロジェクトで例外を使用することに反対する必要があります。全てを一から始め直さなければならないというのなら話は別なのですが。
Windowsコードについて、この規則に対する例外(ダジャレではありません)があります。
実行時型情報(RTTI)
我々は実行時型情報(RTTI)を使用しません。
詳細(抜粋)
実行時に型の問い合わせを行うことは、普通は設計に問題があることを意味します。実行時にオブジェクトの型を知る必要が生じたら、たいていはクラスの設計を見直すべきです。
ユニットテストのときを除いてRTTIを使用しないで下さい。
キャスト
static_cast<>()のようなC++キャストを使用してください。int y = (int)x; or int y = int(x);のような他のキャストを使用しないでください。
ストリーム
ストリームはログを取るためだけに使用してください。
詳細(抜粋)
ログのインターフェースに要求された場合以外にはストリームを使わないでください。代わりにprintf系のルーチンを使用してください。 ストリームの使用にはたくさんの賛成意見や反対意見がありますが、今回は一貫性が議論の決め手になりました。コード中でストリームを使用しないでください。
前置インクリメント/デクリメント
イテレータやその他のテンプレートオブジェクトのインクリメント/デクリメント演算子は前置形式を使用してください。
constの使用
意味が通る場合にはいつでもconstを使用することを強く推奨します。
整数型
C++の組み込み整数型のうち、唯一使用されるのはintです。違う大きさの変数が必要になった場合、int16_tのような大きさが決まった<stdint.h>の整数型を使用してください。
64ビットへの可搬性
コードは64ビットと32ビットで利用できるべきです。表示や比較、構造体のアラインメントの問題を忘れないでください。
プリプロセッサマクロ
マクロには細心の注意を払ってください。マクロよりもインライン関数、enum、const変数のほうが望ましいです。
0とNULL
整数には0、実数値には0.0、ポインタにはNULL、charには'\0'を使用してください。
sizeof
可能ならいつでもsizeof(変数名)をsizeof(型)のかわりに使用してください。
Boost
Boostからは許可されたライブラリのみ使用してください。
詳細
定義
Boostは評価が高く査読済みでフリーなオープンソースライブラリの集合です。
○
Boostのコードは一般にとても質が高く、可搬性が高く、型特性や優れたバインダおよびスマートポインタなどによりC++標準ライブラリが抱える多くの重要な欠落を補えます。標準ライブラリへのTR1による拡張の実装もBoostによって提供されています。
×
Boostのうちいくつかのライブラリは、メタプログラミングやその他の先進的なテンプレート技法、行きすぎた"関数的な"プログラミングスタイルなどの可読性を妨げるコーディング習慣を奨励してしまいます。
結論
コードを読み、維持する可能性のある全ての貢献者に対して高い水準の可読性を維持するために、我々はBoostの機能のうち承認されたものしか許可しません。
現在は以下のライブラリが許可されています。
- Compressed Pair:boost/compressed_pair.hppに収録
- Pointer Contariner:boost/ptr_containerに収録(ただしserializationを除く)
- Array:boost/array.hppに収録
- The Boost Graph Library (BGL):boost/graphに収録(ただしserializationを除く)
- Property Map:boost/property_map.hppに収録
- イテレータの定義に関するIteratorの一部:boost/iterator/iterator_adaptor.hpp, boost/iterator/iterator_facade.hpp, and boost/function_output_iterator.hpp に収録
我々はBoostの他の機能をリストに加えることを前向きに考えており、将来この規則は緩和される可能性があります。
名前付け
最も重要な一貫性に関する規則は名前付けについてのものです。名前のスタイルは名付けられたものがどのような種類のものなのかを、それらの宣言を探さなくても直接に教えてくれます:型、変数、関数、定数、マクロ、etc.
名前付けの規則はとても自由ですが、我々は一貫性が個人の好みよりも重要だと考えます。ですから、あなたが理にかなっていると思うか思わないかに関わらず、規則は規則なのです。
一般的な名前付け規則
関数の名前、変数の名前、ファイル名は説明的であるべきです。省略は避けてください。型や変数は名詞、関数は"命令形"の動詞であるべきです。
ファイル名
ファイル名は全て小文字で、アンダースコア(_)またはダッシュ(-)を含むことができます。あなたのプロジェクトの決まりに従ってください。
詳細
許されるファイル名の例
- my_useful_class.cc
- my-useful-class.cc
- myusefulclass.cc
C++ファイルは.ccで終わり、ヘッダファイルは.hで終わるべきです。
db.hのような/usr/includeに既にあるファイル名を使わないで下さい。
一般に、ファイル名はとても具体的なものにして下さい。例えば、log.hではなくhttp_server_logs.hを使って下さい。FooBarというクラスを定義するのに、foo_bar.hとfoo_bar.ccというファイルの組を持つのはとても一般的なことです。
インライン関数は.hファイルの中になければなりません。もし関数がとても短いのであれば、.hファイルの中に直接入れられるべきです。しかし、関数が多くのコードを含む場合に-inl.hで終わる第三のファイルに入れることは許されます。たくさんのインラインコードを含むクラスについて、以下の3つのファイルが存在し得ます。
url_table.h // The class declaration. url_table.cc // The class definition. url_table-inl.h // Inline functions that include lots of code.
「"-inl.h"ファイル」の項も見て下さい。
型の名前
型の名前は大文字で始まり、新しい単語の度に大文字を入れ、アンダースコアは使わないでください:MyExcitingClass、MyExcitingEnum
変数の名前
変数の名前は全て小文字で、単語と単語の間にはアンダースコアを入れてください。クラスのメンバ変数は後ろにアンダースコアをつけてください。例:my_exciting_local_variable、my_exciting_member_variable_
定数の名前
kの後ろに大文字と小文字で名前を続けてください:kDaysInAWeek
関数の名前
通常の関数は大文字と小文字を使用し、アクセサや値を変更する関数(mutator)は変数の名前と揃えてください:MyExcitingFunction()、MyExcitingMethod()、my_exciting_member_variable()、set_my_exciting_member_variable()
名前空間の名前
名前空間の名前は全て小文字で、プロジェクト名と可能ならディレクトリ構造に基づいているようにしてください:google_awsome_project
列挙子の名前
列挙子は全て大文字で単語と単語の間にはアンダースコアが入るべきです:MY_EXCITING_ENUM_VALUE
マクロの名前
本当はマクロなんか作ろうとしていませんよね?もし作るのであれば、このようにするべきです:MY_MACRO_THAT_SCARES_SMALL_CHILDREN
規則の例外
既存のCやC++のエンティティに似せたものを作っている場合、そちらの名前付け規則に従うこともできます。
詳細
- bigopen() 関数名。open()にならった。
- uint typedef
- bigpos structまたはclass。posにならった。
- sparse_hash_map STL的なエンティティ。STLの名前付け規則に従った。
- LONGLONG_MAX 定数。INT_MAXにならった。
コメント
書く苦しみはありますが、コメントはコードの可読性を保つために絶対に必要です。以下の規則は何をどこでコメントするべきか示しています。しかし覚えておいてください、確かにコメントはとても重要ですが、最良のコードはそれ自身ドキュメントなのです。理にかなった名前を型や変数につけることは、コメントでの説明が必要になるような曖昧な名前をつけることよりも遥かに優れています。
コメントを書くときには、観客に向けて、あなたのコードを理解する必要がある次の貢献者に向けて書くようにしてください。出し惜しみはしないで―次の一人はあなたかもしれないのですから!
コメントのスタイル
あなたの方針が一貫している限り、//と/* */のどちらを使用してもかまいません。
ファイルのコメント
それぞれのファイルは著作権表記から始まり、ファイルの内容の解説が続きます。
クラスのコメント
全てのクラス定義には対応するコメントが存在し、目的や使用法を記述するべきです。
関数のコメント
宣言でのコメントは関数の利用法を記述します。関数の定義でのコメントは処理を記述します。
変数のコメント
一般に、実際の変数の名前はそれが何に使われるのか有用な手がかりを与えるくらい説明的であるべきです。場合によっては、更なるコメントも必要とされるでしょう。
実装のコメント
実装の中で、トリッキーであったり、はっきりしない、興味深い、もしくは重要な部分にはコメントを書くべきです。
句読点、スペル、文法
句読点やスペル、文法には気をつけてください。よく書かれたコメントの方が下手に書かれたコメントよりも読みやすいです。
TODOコメント
短期的なその場しのぎの解決であったり、十分ではあるけど完璧ではないコードにはTODOコメントを書いてください。
フォーマット
コーディングのスタイルやフォーマットは大変自由です。しかし、みんなが同じスタイルを使っていればプロジェクトに参加するのはとても容易になります。個人個人はフォーマット規則の全ての面に賛同したりしないでしょうし、慣れてしまうかもしれません。しかし大切なのは、全ての貢献者がスタイル規則に従うことで、誰もが他人のコードを簡単に読んで理解できることです。
行の長さ
コード中のテキストの各行は80字以内であるべきです。
非ASCII文字
非ASCII文字はまれであるべきです。また、UTF-8を使用するべきです。
スペース vs. タブ
スペースのみを使用してください。毎回スペース2つずつインデントを行ってください。
関数の宣言と定義
戻り値の型は関数名と同じ行に、おさまるなら引数も同じ行にしてください。
関数の呼び出し
おさまるなら1行に、でなければ引数をカッコで包んでください。
詳細
関数の呼び出しは以下のフォーマットを持ちます
bool retval = DoSomething(argument1, argument2, argument3);
もし引数がすべて1行におさまらないなら、後続の行が第一引数に並ぶようにして複数行に分けられるべきです。左カッコの後や右カッコの前にスペースを追加しないでください。
bool retval = DoSomething(averyveryveryverylongargument1,
argument2, argument3);
関数が引数をたくさん持つなら、可読性のために1つにつき1行使うことを考えてみてください。
bool retval = DoSomething(argument1,
argument2,
argument3,
argument4);
関数名が最大の行の長さを超えるくらい長いときには、全ての引数を後続の行に置くことができます。
if (...) {
...
...
if (...) {
DoSomethingThatRequiresALongFunctionName(
very_long_argument1, // 4 space indent
argument2,
argument3,
argument4);
}
条件文
カッコの内側にはスペースがないのが望ましい。elseキーワードは新しい行に置いて下さい。
詳細(抜粋)
if (condition) { // no spaces inside parentheses
... // 2 space indent.
} else { // else goes on the same line as the closing brace.
...
}
ループとswitch文
switch文はブロックのために中カッコを使用できます。空のループは{}またはcontinueを使用するべきです。
詳細
switch文のcaseブロックは、あなたの好みに合わせて中カッコを使用してもいいですし、使用しなくてもいいです。使用するならば、下記のように配置してください。
列挙型に対してでない場合は、switch文は常にdefaultケースを持つべきです(列挙型であれば、捕捉されない値があるときには警告が出ます)。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.
ポインタと参照
ピリオドやアロー演算子のまわりにスペースを置かないでください。ポインタ演算子の後ろにスペースを置かないでください。
詳細
下記は正しいフォーマットのポインタと参照の表現です。
x = *p; p = &x; x = r.y; x = r->y;
以下の点に注意してください。
- メンバにアクセスするとき、ピリオドやアローのまわりにスペースはない。
- ポインタ演算子は*や&の後ろにスペースを持たない。
ポインタ変数や引数を宣言するとき、アスタリスクは型か変数名のとなりに置いてください。
// 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 &
アスタリスクの位置は一つのファイル内では統一してください。既存のファイルを編集するときは、そこでのスタイルに合わせてください。
ブーリアン表現
一行の長さよりも長いブーリアン表現を分割するときは、そのやり方は統一してください。
詳細
この例では、論理AND演算子は常に行の終わりにあります
if (this_one_thing > this_other_thing &&
a_third_thing == a_fourth_thing &&
yet_another & last_one) {
...
}
論理AND演算子が両方とも行の終わりにあることに注意してください。追加のカッコは正しく使われれば可読性の向上に大変役に立つので、自由に挿入してください。
戻り値
return式をカッコでくくらないでください。
詳細
戻り値はカッコでくくるべきではありあせん。
return x; // not return(x);
変数・配列の初期化
=と()のどちらを使ってもかまいません。
プリプロセッサ命令
プリプロセッサ命令はインデントせずに、行のはじめから書いてください。
クラスのフォーマット
節はpublic、protected、privateの順で、インデントはスペース1つ。
詳細
クラス宣言の基本的なフォーマット(コメントが欠けています、どのようなコメントが必要かは「クラスのコメント」の項を見てください)
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文字の規則には従う
- public:、protected:、private:キーワードはスペース1つのインデント
- 最初のものを除いて、これらのキーワードの手前は空行。ただし、小さなクラスではこの限りでない。
- これらのキーワードの後に空行を置いてはいけない。
- public節が最初、protected節が続き、最後にprivate節。
- それぞれの節の中での宣言の順番については「宣言の順序」の項を見てください。
初期化子リスト
コンストラクタの初期化子リストは全てを1行に、もしくはスペース4つでインデントされた後続の行に分割できます。
詳細
2通りの初期化子リストのフォーマットが許されています。
// 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();
...
}
名前空間のフォーマット
名前空間の中身はインデントしないでください。
水平方向の空白
水平方向の空白の使用は場所によります。行の後ろに空白を置かないでください。
垂直方向の空白
垂直方向の空白の使用は最小限に留めてください。
詳細
これは規則というより原則です。使わなくてすむなら空行を使わないでください。特に、関数と関数の間に1〜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
}
規則の例外
ここまで記されてきた決まりは強制的です。ただ、すべてのよい規則と同じように例外があります。
既存のコード
このスタイルガイドに沿わないコードに関わるときは、あなたはこの規則から外れます。
Windowsコード
Windowsプログラマは、主にWindowsヘッダやその他のマイクロソフトのコードに基づいて独自のコーディング規則を作り上げてきました。我々はあなたのコードが誰でも簡単に理解できるものになることを望むので、あらゆるプラットフォームでC++を書くあらゆる人に向けて一つのガイドラインを示します。
詳細
もし広く普及したWindowsのスタイルにあなたが親しんでいたら、今までの指針を忘れているかもしれないのでもう一度おさらいしてみましょう。
- ハンガリアン記法は使わないで下さい(例えば、整数値をiNumと名付けたり)。グーグルの名前付け規則を使って下さい。ソースファイルには.ccという拡張子をつけてください。
- Windowsは基本的な型にDWORDやHANDLEなどたくさんの異名をつけています。WindowsAPI関数を呼び出すときにこれらの型を使うのは完全に許されていますし、推奨されます。ですが、可能な限り基礎的なC++の型を使って下さい。例えば、LPCTSTR の代わりに const TCHAR * を使って下さい。
- Microsoft Visual C++でコンパイルするときは、コンパイラの警告レベルを3以上にして、すべての警告をエラーとして扱って下さい。
- グーグルの標準インクルードガードの代わりに#pragma onceを使ったりしないで下さい。インクルードガード中のパスは、あなたのプロジェクトツリーの先頭からの相対パスにするべきです。
- さらに言うなら、絶対に使わなければならない場合を除いて#pragmaや__declspecのような非標準の拡張はいっさい使わないで下さい。__declspec(dllimport)や__declspec(dllexport)を使うのは許されますが、コードを共用するときに簡単に無効にできるようDLLIMPORTやDLLEXPORTのようなマクロの形で使用して下さい。
ところで、Windowsで作業をする上でたまに必要になる規則がいくつかあります。
- 通常の場合、実装の多重継承は禁止されますが、COMやいくつかのATL/WTLのクラスを使うときには必要になります。COMやATL/WTLのクラスやインターフェースを実装する際には、実装の多重継承は許可されます。
- コード中で例外を使うべきではありませんが、ATLやVisual C++に付属するいくつかのSTLの中では広く使われています。ATLを使う際には、例外を無効にするために_ATL_NO_EXCEPTIONSを定義する必要があります。あなたはSTL中の例外を無効にできるか調査すべきですが、できないのであれば例外を有効に扱うようコンパイラを設定してもかまいません。(STLをコンパイルできるようにすることだけが目的なのを忘れないで下さい。あなた自信は例外を扱うコードを書くべきではありません。)
- プリコンパイル済みヘッダを扱う一般的な方法は、各ソースファイルの先頭で普通は"StdAfx.h"や"precompile.h"のような名前になっているヘッダファイルをインクルードすることです。コードを他のプロジェクトと共用するのがより簡単になるよう、このファイルを明示的にインクルードするのを避けて(precompile.cc中でのものを除く)、/FIコンパイラオプションを使用してこのファイルを自動的にインクルードして下さい。
- ふつう"resource.h"という名前がついていてマクロしか含まないリソースヘッダについては、このスタイルガイドに合わせる必要はありません。
おわりに
常識を働かせて、一貫性を守ってください。
あなたがコードを編集しているなら、数分間を使って周りのコードを見てそのスタイルを見定めてください。そこでifのカッコの周りにスペースが使われていたら、あなたもそうするべきです。そこでコメントが星でできた小さな箱に囲まれていたら、あなたもコメントを星でできた小さな箱で囲うべきです。
スタイルガイドを持つことの要点は、あなたがどのように話しているのかではなく、あなたが何を言っているのかにみんなが集中できるようなコードを書く共通の言葉を持つことです。我々はみなさんが言葉を知ることができるようスタイルについての広範囲な規則を提示しました。しかしその場その場でのスタイルというのもまた重要です。あなたがファイルに追加しようとしているコードが周囲の既存のコードとまったく違って見えたら、その不連続は読む人のリズムを完全に乱してしまうでしょう。これは避けてください。
OK、コードを書くことについては十分書きました、コードそのものはもっと面白いですよ。楽しんでください!
Keyword(s):
References:[制作物]