337 lines
6.3 KiB
Markdown
337 lines
6.3 KiB
Markdown
# C++ コーディング規約
|
||
|
||
## 1. 一般的なガイドライン
|
||
|
||
1. **モダン C++(C++17 以上)** を前提とする。
|
||
2. 生ポインタより、まず **`std::unique_ptr` / `std::shared_ptr` / `std::vector` など RAII** を優先する。
|
||
3. 例外を使う場合は、**例外 or エラーコードのどちらかに統一**する。
|
||
4. `new` / `delete` は基本的に直接使わず、スマートポインタやコンテナを使う。
|
||
5. ヘッダ/ソース分割は `*.h` / `*.cpp`(または `*.hpp` / `*.cpp`)で行う。
|
||
6. 自動整形には **`clang-format`** を利用する。
|
||
|
||
---
|
||
|
||
## 2. コメント/ドキュメント
|
||
|
||
### 2.1 ファイルコメント
|
||
|
||
```cpp
|
||
// user_service.h - ユーザー関連のユースケースを提供するクラス群
|
||
#pragma once
|
||
|
||
// ...
|
||
```
|
||
|
||
### 2.2 クラスコメント(Doxygen 推奨)
|
||
|
||
```cpp
|
||
/**
|
||
* @brief ユーザーを管理するサービスクラス。
|
||
*
|
||
* ユーザーの作成、取得、削除などの機能を提供する。
|
||
*/
|
||
class UserService {
|
||
public:
|
||
/// コンストラクタ
|
||
explicit UserService(UserRepository& repo);
|
||
|
||
/// ユーザーを作成する
|
||
User createUser(const std::string& name, int age);
|
||
|
||
private:
|
||
UserRepository& repo_;
|
||
};
|
||
```
|
||
|
||
### 2.3 メソッドコメント
|
||
|
||
```cpp
|
||
/**
|
||
* @brief ユーザーをIDで取得する。
|
||
*
|
||
* @throws std::runtime_error ユーザーが存在しない場合。
|
||
*/
|
||
User UserService::getUserById(int id);
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 命名規則
|
||
|
||
1. **クラス名/構造体名**: `CamelCase`
|
||
|
||
```cpp
|
||
class UserService;
|
||
struct HttpRequest;
|
||
```
|
||
|
||
2. **メソッド・関数名**: `camelCase` または `snake_case`(プロジェクト内で統一)
|
||
|
||
```cpp
|
||
void addUser(const User& user);
|
||
int find_user(const std::string& name); // プロジェクト方針次第
|
||
```
|
||
|
||
3. **メンバ変数**:
|
||
|
||
* プレフィックスやサフィックスを付けるスタイルが多い
|
||
例: `snake_case_` / `m_name` / `_name` など
|
||
|
||
```cpp
|
||
class User {
|
||
public:
|
||
explicit User(std::string name, int age)
|
||
: name_(std::move(name)), age_(age) {}
|
||
|
||
private:
|
||
std::string name_;
|
||
int age_;
|
||
};
|
||
```
|
||
|
||
4. **定数**:
|
||
|
||
* グローバル定数には `k` プレフィックスを使う場合も多い。
|
||
|
||
```cpp
|
||
constexpr int kMaxUserCount = 1000;
|
||
```
|
||
|
||
5. **名前空間**: すべて小文字でプロジェクト名などを使う。
|
||
|
||
```cpp
|
||
namespace myapp::user {
|
||
// ...
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. インクルードガイドライン
|
||
|
||
1. ヘッダでのインクルードは **最小限** にする。前方宣言で済むなら前方宣言を使う。
|
||
|
||
```cpp
|
||
// user_service.h
|
||
#pragma once
|
||
|
||
#include <string>
|
||
|
||
namespace myapp {
|
||
|
||
class UserRepository; // 前方宣言
|
||
|
||
class UserService {
|
||
public:
|
||
explicit UserService(UserRepository& repo);
|
||
// ...
|
||
private:
|
||
UserRepository& repo_;
|
||
};
|
||
|
||
} // namespace myapp
|
||
```
|
||
|
||
2. ソースファイルでは対応するヘッダをまずインクルードし、その後に標準/外部ライブラリ。
|
||
|
||
```cpp
|
||
// user_service.cpp
|
||
#include "user_service.h"
|
||
|
||
#include "user_repository.h"
|
||
|
||
#include <stdexcept>
|
||
```
|
||
|
||
3. インクルード順は以下を推奨:
|
||
|
||
1. 自分のヘッダ
|
||
2. 同じモジュールのヘッダ
|
||
3. 標準ライブラリ
|
||
4. サードパーティヘッダ
|
||
|
||
---
|
||
|
||
## 5. エラーハンドリング
|
||
|
||
### 5.1 例外を使う場合
|
||
|
||
1. ロジック上の失敗には `throw` で例外を投げ、呼び出し側で `try`/`catch`。
|
||
|
||
```cpp
|
||
User UserService::getUserById(int id)
|
||
{
|
||
auto user = repo_.findById(id);
|
||
if (!user) {
|
||
throw std::runtime_error("User not found");
|
||
}
|
||
return *user;
|
||
}
|
||
```
|
||
|
||
2. 例外の種類は、`std::runtime_error` / `std::invalid_argument` などを使い分ける。
|
||
|
||
3. ライブラリ側では「例外を投げる API」と「エラーコードを返す API」を明確に分ける。
|
||
|
||
### 5.2 例外を使わない場合
|
||
|
||
1. 戻り値に `std::optional<T>` や `expected` パターン(独自実装)を使う。
|
||
|
||
```cpp
|
||
std::optional<User> UserService::tryGetUserById(int id)
|
||
{
|
||
return repo_.findById(id);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 複数ファイル間の分割(ヘッダ / ソース)
|
||
|
||
### 6.1 例: User と UserService
|
||
|
||
```text
|
||
include/
|
||
user.h
|
||
user_service.h
|
||
src/
|
||
user.cpp
|
||
user_service.cpp
|
||
main.cpp
|
||
```
|
||
|
||
#### `user.h`
|
||
|
||
```cpp
|
||
#pragma once
|
||
|
||
#include <string>
|
||
|
||
namespace myapp {
|
||
|
||
class User {
|
||
public:
|
||
User(int id, std::string name);
|
||
|
||
int id() const;
|
||
const std::string& name() const;
|
||
|
||
private:
|
||
int id_;
|
||
std::string name_;
|
||
};
|
||
|
||
} // namespace myapp
|
||
```
|
||
|
||
#### `user.cpp`
|
||
|
||
```cpp
|
||
#include "user.h"
|
||
|
||
namespace myapp {
|
||
|
||
User::User(int id, std::string name)
|
||
: id_(id), name_(std::move(name))
|
||
{
|
||
}
|
||
|
||
int User::id() const
|
||
{
|
||
return id_;
|
||
}
|
||
|
||
const std::string& User::name() const
|
||
{
|
||
return name_;
|
||
}
|
||
|
||
} // namespace myapp
|
||
```
|
||
|
||
#### `user_service.h`
|
||
|
||
```cpp
|
||
#pragma once
|
||
|
||
#include <memory>
|
||
|
||
#include "user.h"
|
||
|
||
namespace myapp {
|
||
|
||
class UserRepository;
|
||
|
||
class UserService {
|
||
public:
|
||
explicit UserService(UserRepository& repo);
|
||
|
||
User createUser(const std::string& name, int age);
|
||
|
||
private:
|
||
UserRepository& repo_;
|
||
};
|
||
|
||
} // namespace myapp
|
||
```
|
||
|
||
#### `user_service.cpp`
|
||
|
||
```cpp
|
||
#include "user_service.h"
|
||
|
||
#include "user_repository.h"
|
||
|
||
namespace myapp {
|
||
|
||
UserService::UserService(UserRepository& repo)
|
||
: repo_(repo)
|
||
{
|
||
}
|
||
|
||
User UserService::createUser(const std::string& name, int age)
|
||
{
|
||
// 仮実装: ID採番して保存するなど
|
||
int newId = repo_.nextId();
|
||
User user(newId, name);
|
||
repo_.save(user);
|
||
return user;
|
||
}
|
||
|
||
} // namespace myapp
|
||
```
|
||
|
||
---
|
||
|
||
## 7. clang-format / clang-tidy / VSCode 設定
|
||
|
||
### 7.1 `.clang-format`(C と共有してもOK)
|
||
|
||
```yaml
|
||
BasedOnStyle: LLVM
|
||
IndentWidth: 4
|
||
UseTab: Never
|
||
ColumnLimit: 100
|
||
AllowShortIfStatementsOnASingleLine: false
|
||
BreakBeforeBraces: Attach
|
||
NamespaceIndentation: All
|
||
```
|
||
|
||
### 7.2 VSCode 設定例
|
||
|
||
```json
|
||
{
|
||
"[cpp]": {
|
||
"editor.defaultFormatter": "ms-vscode.cpptools",
|
||
"editor.formatOnSave": true
|
||
},
|
||
"C_Cpp.clang_format_style": "file",
|
||
|
||
// clang-tidy を使う場合
|
||
"C_Cpp.codeAnalysis.clangTidy.enabled": true,
|
||
|
||
"files.trimTrailingWhitespace": true,
|
||
"files.insertFinalNewline": true
|
||
}
|
||
```
|