6. 記法

6.1. クラス

6.1.1. 規約事項 36

クラスのpublic、protected、およびprivateセクションは、その順序で宣言されます。 (publicセクションは、privateセクションの前に宣言されたprotectedセクションの前に宣言されます)

6.1.2. 規約事項 37

テンプレート関数を除いて、メンバ関数をクラス宣言内で実装してはいけません。 (テンプレート関数は、現行のコンパイラ仕様上、クラス宣言内に実装することを避けることができません)

6.1.3. 規約事項 38

インライン関数は、クラス宣言の後に別のブロックで実装する必要があります。

6.1.4. 推奨事項 11

メンバ変数にアクセサがあり、ミューテータがない場合、アクセッサは変数と同じ名前を持ち、アンダースコアのプレフィックスを付けません。 メンバー変数にアクセサーとミューテータの両方がある場合、アクセサ名にはプレフィックス”get”が付き、ミューテータ名にはプレフィックス”set”が付きます。

publicセクションを最初に配置することで、ユーザーにとって興味のあるものはすべて、 クラス定義の最初に集められます。protectedセクションは、クラスを継承することを考慮するとき、 デザイナーにとって興味深いかもしれません。privateセクションには、最も一般的な関心事ではない詳細が含まれています。

クラス宣言内で実装されたメンバー関数は、自動的にインライン関数になります。クラス宣言はコンパクトでなく、 メンバー関数の実装が含まれていると読みにくくなります。インライン関数の実装がクラス宣言の外に置かれていると、 インラインメンバ関数が通常のメンバ関数になりやすくなります。

インライン関数の定義方法の例を以下に示します。

例4
class Foundation_API UUID
{
public:
    //...
    bool operator == (const UUID& uuid) const;
    bool operator != (const UUID& uuid) const;
    bool operator < (const UUID& uuid) const;
    bool operator <= (const UUID& uuid) const;
    bool operator > (const UUID& uuid) const;
    bool operator >= (const UUID& uuid) const;
    //...
};

//
// inlines
//
inline bool UUID::operator == (const UUID& uuid) const
{
    return compare(uuid) == 0;
}
inline bool UUID::operator != (const UUID& uuid) const
{
    return compare(uuid) != 0;
}

//...

アクセサおよびミューテータの例を以下に示します。

例5
class Property
{
public:
    Property(const std::string& name);
    Property(const Property& prop);
    ~Property();
    Property& operator = (const Property&);
    const std::string& name();
    void setValue(const std::string& value);
    const std::string& getValue() const;
private:
    Property();
    std::string _name;
    std::string _value;
};

6.2. 関数

6.2.1. 推奨事項 12

関数を宣言するときは、先頭のかっこと最初の引数(ある場合)を関数名と同じ行に記載します。 スペースと可読性が許せば、他の引数と閉じかっこも関数名と同じ行に記載することができます。 それ以外の場合、追加の引数はそれぞれ別の行に記載し、単一のタブでインデントします。 閉じかっこは、最後の引数の直後に記載します。

長い関数の宣言例を以下に示します。

例6
DateTime& assign(
    int year,
    int month,
    int day,
    int hour = 0,
    int minute = 0,
    int second = 0,
    int millisecond = 0,
    int microseconds = 0);

6.2.2. 推奨事項 13

関数名の直後に左かっこを記述してください。 関数名、左かっこ、および最初の引数の間にはスペースはありません。また、最後の引数と閉じかっこの間にスペースはありません。

6.3. テンプレート

6.3.1. 規約事項 39

テンプレートキーワードは、テンプレート引数リストと共に、 後続のクラスまたは関数定義の前の別の行に記載します。

6.4. 複合ステートメント

6.4.1. 推奨事項 14

ブロックを囲む中括弧( “{}”)は、ブロックの直前と直後の別々の行で、同じ列に記載します。 中カッコの配置方法は、CとC++双方で、最大の議論の対象となっているようです。 私たちの意見では、コードが最も読みやすくなる前述の記法をお勧めします。 他のコーディングスタイルでは、よりコンパクトな記法が推奨されることもあるでしょう。

6.5. 制御文

6.5.1. 推奨事項 15

制御文のキーワードと制御式の開始かっこの間には、スペースを置きます。 開始かっこと式の間にはスペースを置きません。式と閉じ括弧の間にもスペースを置きません。

6.5.2. 推奨事項 16

制御文 if、else、while、forおよびdoは、たとえ空のブロックであっても、1つのステートメントだけで構成されていても、 後ろにブロックを記載する必要があります。

しばしば、ループで行われるすべてのことが、ループステートメント自体の1行に簡単に書き込まれることがあります。 その後、行末にセミコロンでステートメントを締めくくるかもしれません。 この記法は、コードを読むときに、セミコロンを見逃しやすいので、誤解を招く可能性があります。 また、セミコロンは誤って削除される可能性があり、見つけにくいバグにつながります。 そのような場合には、文の後ろに空のブロックを置いて、コードが何をしているかを明確にした方が良いでしょう。 さらに良いのは、この記法を完全に避けることです。

場合によっては、よりコンパクトなコードは、単一のステートメントだけを含む多くのブロックを持つコードよりも読みやすくなります。 原則として、厳密なスタイルの遵守よりも、可読性を常に優先させるべきです。

ブロックと単一行ステートメントの例を以下に示します。

例7
int ASCIIEncoding::convert(int ch, unsigned char* bytes, int length) const
{
    if (ch >= 0 && ch <= 127)
    {
        *bytes = (unsigned char) ch;
        return 1;
    }
    else return 0;
}

単一行の制御文によってコードをコンパクトに保つ​ち、可読性が向上される例を以下に示します。

例8
void MessageHeader::splitParameters(
    const std::string& s,
    std::string& value,
    NameValueCollection& parameters)
{
    value.clear();
    parameters.clear();
    std::string::const_iterator it = s.begin();
    std::string::const_iterator end = s.end();
    while (it != end && isspace(*it)) ++it;
    while (it != end && *it != ';') value += *it++;
    Poco::trimRightInPlace(value);
    if (it != end) ++it;
    splitParameters(it, end, parameters);
}

6.6. ポインタと参照

6.6.1. 推奨事項 17

関節演算子「*」とアドレス「&」は、型名の隣に記載する必要があります。 「*」と「&」は、型定義の一部であることを強調するために、変数の名前ではなく、 変数の型とともに記述する必要があります。つまり、* iがintであるのではなく、iがint* であると明示的に示すのです。 Cでは、伝統的に、同じ宣言文でいくつかの変数を宣言するときに間違いを起こす可能性を減らすため、 「*」は変数名の隣に記載することを推奨しています。(演算子 「*」は、隣接する変数にのみ影響します) しかし、このコーディングスタイルではそもそも、同じステートメント内での複数の変数の宣言を推奨していません。 従って、このようなアドバイスは無用です。

6.6.2. 規約事項 40

1つのステートメントで複数の変数を宣言してはいけません。

6.7. その他

6.7.1. 推奨事項 18

”.”または “->”のまわりにスペースを使用しないでください。 単項演算子とオペランドの間にもスペースを入れてはいけません。

6.7.2. 推奨事項 19

インデントはタブで行い、タブ内のスペースの数はエディタで4に設定します。 3回もインデントを行うと、行頭から何個のスペースがあるのか、もはや直感的に分かりません。 このため、スペースでインデントされたコードは、厄介なものになります。