404 Not Found

404 Not Found


nginx

例外処理

プログラムの実行時、[必ず予期せぬ事態が発生する]:ファイル[が存在しない]、メモリ[不足]、[ネットワーク切断]……

[何もしなければ]、プログラム[はクラッシュする]。

例外処理[とは]、プログラムの[「エアバッグ」]のようなもの――[問題が発生した際]、[直接クラッシュするのではなく]、[優雅に対処する]ことである。


1. 例外処理[基礎]

(1) 1.1 例外とは何か?

例外[とは]プログラムの実行中に[発生する]エラー[または予期せぬ状況]のことです。

[よくある]例外:


(2) 1.2 例外処理[三要素]

C++の例外処理[3つのキーワードを使用]:

[キーワード] [機能]
try [エラーが発生する可能性のある]コード
catch [例外の捕捉と処理]
throw 例外をスローする

(3) 1.3 [基本]例

例:[ゼロ除算]例外 (難易度 ⭐)

▶ サンプル 1: codeexample (難易度 ⭐)

CPP
#include iostream

int divide(int a, int b) {
 if (b == 0) {
 throw "0!"; // ...
 }
 return a / b;
}

int main() {
 try {
 std::cout << divide(10, 2) << std::endl; // ...
 std::cout << divide(10, 0) << std::endl; // ...
 }
 catch (const char* msg) { // ...
 std::cerr << ":" << msg << std::endl;
 }
 
 std::cout << "..." << std::endl;
 return 0;
}
▶ 試してみよう

[実行結果]:

TEXT
5:0!

💡 ヒント:



2. 例外タイプ

(1) 2.1 [スローされた]型

throw [投げられる][あらゆる]タイプ

タイプ
[基本]タイプ throw 42;
文字列 throw "error";
[標準]例外 throw std::runtime_error("error");
[カスタム]例外 throw MyException();

(2) 2.2 [複数の]例外の捕捉

例:[異なる]type[の]例外を捕捉する (難易度 ⭐⭐)

CPP
#include iostream
### (3) ▶ 2:(⭐)

#include string

void process(int value) {
 if (value == 0) {
 throw 0; // int
 }
 if (value < 0) {
 throw std::string("..."); // string
 }
}

int main() {
 try {
 process(-5);
 }
 catch (int e) {
 std::cerr << "int:" << e << std::endl;
 }
 catch (const std::string& e) {
 std::cerr << "string:" << e << std::endl;
 }
 
 return 0;
}


3. [標準]例外

(1) 3.1 std::exception[階層]

C++の[標準ライブラリには一連の]例外クラスが定義されており、[それらはすべて] stdexcept [に含まれています]:

CPP
std::exception
 ├── std::logic_error
 │ ├── std::invalid_argument
 │ ├── std::out_of_range
 │ └── std::length_error
 └── std::runtime_error
 ├── std::overflow_error
 └── std::underflow_error

(2) 3.2 [常用標準]の例外

例外クラス [説明]
std::invalid_argument [無効なパラメータ]
std::out_of_range [越界]
std::runtime_error 実行時エラー
std::bad_alloc メモリ[割り当て失敗](new[失敗])

例:[使用基準]例外 (難易度 ⭐⭐)

CPP
#include iostream
#include stdexcept
#include vector

int main() {
 std::vectorint v = {1, 2, 3};
 
 try {
 v.at(10); // ...
 }
 catch (const std::out_of_range& e) {
 std::cerr << ":" << e.what() << std::endl;
 }
 
 return 0;
}


4. [カスタム]例外

(1) 4.1 inheritancestd::exception

[ベストプラクティス]: [カスタム]例外クラスの継承 std::exception

例:[カスタム]例外クラス (難易度 ⭐⭐⭐)

CPP
#include iostream
#include exception
#include string

// ...
class MyException : public std::exception {
private:
 std::string msg;
 
public:
 MyException(const std::string& msg) : msg(msg) {}
 
 const char* what() const noexcept override {
 return msg.c_str();
 }
};

int main() {
 try {
 throw MyException("...");
 }
 catch (const MyException& e) {
 std::cerr << ":" << e.what() << std::endl;
 }
 
 return 0;
}


5. 例外[安全]

(1) 5.1 例外[安全]とは何か?

例外[安全]とは、[たとえ]例外がスローされたとしても、プログラムが[一貫性のある状態]([リソースのリークがない]、[データが破損しない])を[維持できる]ことを指します。

[3つの保証レベル]:

  1. [基本保証]:プログラム[状態は一致している]、[ただし変化する可能性がある]
  2. [強保証]:[操作は成功するか]、[あるいは完全にロールバックされる]([何も起こらなかったかのように])
  3. [例外を投げない][保証]:この関数は[決して]例外を投げません

(2) 5.2 RAII――[リソース管理の強力なツール]

RAII(Resource Acquisition Is Initialization):[オブジェクト]がリソースを管理し、デストラクタが自動的にリソースを解放する。

例:[スマートポインタ]を使って[例外処理を][安全に][保証する] (難易度 ⭐⭐⭐)

CPP
#include iostream
#include memory

void process() {
 // unique_ptr,
 std::unique_ptrint p(new int(42));
 
 // ... exception's ...
 
 std::cout << *p << std::endl;
} // p

int main() {
 try {
 process();
 }
 catch (...) {
 std::cerr << "..." << std::endl;
 }
 return 0;
}


6. noexcept[キーワード]

基本的な使い方

C++11[導入] noexcept、[宣言]function[は]例外をスローしない

例:[声明不抛]例外 (難易度 ⭐)

CPP
void safeFunction() noexcept {
 // ...
}

void unsafeFunction() {
 // ...
}

💡 ヒント:


❓ よくある質問

Q:[いつ]exceptionを使うのですか? A:[真に予期せぬ][状況]に[使用し]、[通常の制御]には[使用しません]。


Q:catch(...)とは何ですか? A:[すべての]例外を[捕捉]し、[通常はリソースを解放した後、再び例外をスローするために使用されます]。

CPP
try {
 // ...
}
catch (...) {
 // ...
 throw; // ...
}

Q:コンストラクタで[例外をスロー][できますか]? A:[できます]が、[メモリリークに注意]してください。[スマートポインタ][または]RAII[を使ってリソースを管理]してください。


📖 まとめ

[知識ポイント] [要点]
try-catch-throw 例外処理[三要素]
[標準]例外 std::runtime_error[など]
[カスタム]例外 継承 std::exception
例外[安全] RAII[リソースのリークを防止]
noexcept [宣言]関数[例外を投げない]

📝 練習問題

  1. **初心者向け(難易度 ⭐):[除算を行う]関数を書き、[除数が] 0 [の場合に] std::runtime_error をスローし、[main 関数内で] try/catch を使って [エラーを捕捉し]、[エラーメッセージを] 出力する。

  2. **中級(難易度 ⭐⭐):[独自の]例外クラス(std::exceptionを継承)を定義し、[エラー]コードと[エラーの説明]という2つのフィールドを含め、throw文で投げ、catchブロックで捕捉する。

  3. **上級(難易度 ⭐⭐⭐):[「リソースガード」]クラスを実装し、コンストラクタで[リソースを取得]し、デストラクタで[リソースを解放]するようにする。[途中で]例外がスローされた場合でも、[リソースは正しく解放される]ようにする(RAIIの[原理])。



[次のレッスン]:ファイル[応用操作](#41)

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%