[大杯C++14例外処理
32233 ワード
Created: June 6, 2021 11:26 AM
Tag: exception handling, function try, rethrow, stack unwinding, std::exception
14.1異常処理のデフォルト異常処理
消滅者のうち、 スマートポインタを使用すると、領域を離れると(
Tag: exception handling, function try, rethrow, stack unwinding, std::exception
14.1異常処理のデフォルト異常処理
異常処理は、try
、catch
(投げ出された異常を受け付けて処理)、throw
(投げ出された異常)文で行うことができる.この方法は文法的には簡潔だが、演技には不利なので、場合によっては使用を制限しなければならない.また,ランタイムエラー(runtime error)はデータ型に応じて厳密に動作するため注意が必要である.ellipses
文でこれを防ぐことができます.#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(void)
{
double x;
cin >> x;
try
{
if (x < 0.0) throw std::string("Negative input");
cout << std::sqrt(x) << endl;
}
catch (std::string error_message) // <- 자료형에 주의
{
// do something to respond
cout << error_message << endl;
}
return (0);
}
14.2異常処理とスタック後退スタック展開 #include <iostream>
using namespace std;
void last() throw(int) // throw(int) <- exception specifier: int type의 예외를 던질 수도 있음을 명시!
// 불필요한것 아니냐는 견해
// 예외를 던질 가능성이 있는 함수
{
cout << "last " << endl;
cout << "throws exception" << endl;
throw -1; // 다음부분 실행하지 않고 throw
cout << "end last " << endl;
}
void third()
{
cout << "third" << endl;
last(); // 다음부분 실행하지 않고 throw
cout << "end third" << endl;
}
void second()
{
cout << "second" << endl;
try
{
third();
}
catch (double) // throw는 int로 되었는데 double로 밖에 catch하지 못한다면 계속해서 날아간다
{
cerr << "second caught double exception" << endl;
}
cout << "end second " << endl;
}
void first()
{
cout << "first" << endl;
try
{
second();
}
catch (int) // catch!
{
cerr << "first caught int exception" << endl;
}
cout << "end first" << endl;
}
int main(void)
{
cout << "start" << endl;
try
{
first();
}
catch (int)
{
cerr << "main caught int exception" << endl;
// clog
}
// uncaught exceptions 못잡는 오류가 발생하는 경우
catch (...) // catch-all handlers
{
cerr << "main caught ellipses exception" << endl;
}
cout << "end main" << endl;
return (0);
}
14.3例外クラス(カスタムデータ型)と継承時の注意点
例外クラスが継承されると、catch
文でオブジェクトのクリップのような現象が発生する可能性があります.このような状況を防ぐ方法とrethrow
について説明しましょう.#include <iostream>
using namespace std;
class Exception
{
public:
void report()
{
cerr << "Exception report" << endl;
}
};
class ArrayException : public Exception
{
public:
void report()
{
cerr << "Array exception" << endl;
}
};
class MyArray
{
private:
int m_data[5];
public:
int &operator [] (const int &index)
{
if (index < 0 || index >= 5) throw ArrayException();
return (m_data[index]);
}
};
void doSomething()
{
MyArray my_array;
try
{
my_array[100];
}
catch (const int &x)
{
cerr << "exception" << x << endl;
}
catch (ArrayException &e)
{
e.report();
throw e; // rethrow
// throw; // 객체 잘림 발생하지 않음
}
catch (Exception &e)
// catch (Exception &e)이 먼저 작성되어 있다면
// 받는 쪽에서 ArrayException이 아닌 Exception으로 받기 때문에
// 객체잘림과 유사하게 Exception report 출력
{
e.report();
}
}
int main(void)
{
try
{
doSomething();
}
catch(ArrayException &e)
{
cout << "main()" << endl; // rethrow 한것을 받는다
e.report();
}
return (0);
}
14.4 std::例外の概要
異なる状況に対する異常処理はstd::exception
によって実現された.それをどのように利用するかを理解してみましょう.#include <iostream>
#include <exception> // <-
#include <string>
class CustomException : public std::exception
{
public:
const char *what() const noexcept override
{
return ("Custom exception");
}
};
int main(void)
{
try
{
throw std::runtime_error("Bad thing happend");
}
catch (std::length_error &exception)
{
std::cerr << exception.what() << std::endl;
}
catch (std::exception &exception)
{
std::cerr << exception.what() << std::endl;
}
return (0);
}
14.5関数try #include <iostream>
using namespace std;
class A
{
private:
int m_x;
public:
A(int x) : m_x(x)
{
if (x <= 0)
throw 1;
}
B(int x) try : A(x)
{
// do init
}
catch (...)
{
cout << "catch in B constructor " << endl;
// throw; // 없어도 있는것처럼 작동!
}
};
class B : public A
{
public:
B (int x)
: A(x) // init
{
}
};
void doSomething()
{
try
{
throw - 1;
}
catch (...)
{
cout << "catch in doSomething()" << endl;
}
}
int main(void)
{
try
{
// doSomething()
B b(0);
}
catch (...)
{
cout << "catch in main(void)" << endl;
}
return (0);
}
14.6異常処理のリスクと欠点
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(void)
{
double x;
cin >> x;
try
{
if (x < 0.0) throw std::string("Negative input");
cout << std::sqrt(x) << endl;
}
catch (std::string error_message) // <- 자료형에 주의
{
// do something to respond
cout << error_message << endl;
}
return (0);
}
#include <iostream>
using namespace std;
void last() throw(int) // throw(int) <- exception specifier: int type의 예외를 던질 수도 있음을 명시!
// 불필요한것 아니냐는 견해
// 예외를 던질 가능성이 있는 함수
{
cout << "last " << endl;
cout << "throws exception" << endl;
throw -1; // 다음부분 실행하지 않고 throw
cout << "end last " << endl;
}
void third()
{
cout << "third" << endl;
last(); // 다음부분 실행하지 않고 throw
cout << "end third" << endl;
}
void second()
{
cout << "second" << endl;
try
{
third();
}
catch (double) // throw는 int로 되었는데 double로 밖에 catch하지 못한다면 계속해서 날아간다
{
cerr << "second caught double exception" << endl;
}
cout << "end second " << endl;
}
void first()
{
cout << "first" << endl;
try
{
second();
}
catch (int) // catch!
{
cerr << "first caught int exception" << endl;
}
cout << "end first" << endl;
}
int main(void)
{
cout << "start" << endl;
try
{
first();
}
catch (int)
{
cerr << "main caught int exception" << endl;
// clog
}
// uncaught exceptions 못잡는 오류가 발생하는 경우
catch (...) // catch-all handlers
{
cerr << "main caught ellipses exception" << endl;
}
cout << "end main" << endl;
return (0);
}
14.3例外クラス(カスタムデータ型)と継承時の注意点
例外クラスが継承されると、catch
文でオブジェクトのクリップのような現象が発生する可能性があります.このような状況を防ぐ方法とrethrow
について説明しましょう.#include <iostream>
using namespace std;
class Exception
{
public:
void report()
{
cerr << "Exception report" << endl;
}
};
class ArrayException : public Exception
{
public:
void report()
{
cerr << "Array exception" << endl;
}
};
class MyArray
{
private:
int m_data[5];
public:
int &operator [] (const int &index)
{
if (index < 0 || index >= 5) throw ArrayException();
return (m_data[index]);
}
};
void doSomething()
{
MyArray my_array;
try
{
my_array[100];
}
catch (const int &x)
{
cerr << "exception" << x << endl;
}
catch (ArrayException &e)
{
e.report();
throw e; // rethrow
// throw; // 객체 잘림 발생하지 않음
}
catch (Exception &e)
// catch (Exception &e)이 먼저 작성되어 있다면
// 받는 쪽에서 ArrayException이 아닌 Exception으로 받기 때문에
// 객체잘림과 유사하게 Exception report 출력
{
e.report();
}
}
int main(void)
{
try
{
doSomething();
}
catch(ArrayException &e)
{
cout << "main()" << endl; // rethrow 한것을 받는다
e.report();
}
return (0);
}
14.4 std::例外の概要
異なる状況に対する異常処理はstd::exception
によって実現された.それをどのように利用するかを理解してみましょう.#include <iostream>
#include <exception> // <-
#include <string>
class CustomException : public std::exception
{
public:
const char *what() const noexcept override
{
return ("Custom exception");
}
};
int main(void)
{
try
{
throw std::runtime_error("Bad thing happend");
}
catch (std::length_error &exception)
{
std::cerr << exception.what() << std::endl;
}
catch (std::exception &exception)
{
std::cerr << exception.what() << std::endl;
}
return (0);
}
14.5関数try #include <iostream>
using namespace std;
class A
{
private:
int m_x;
public:
A(int x) : m_x(x)
{
if (x <= 0)
throw 1;
}
B(int x) try : A(x)
{
// do init
}
catch (...)
{
cout << "catch in B constructor " << endl;
// throw; // 없어도 있는것처럼 작동!
}
};
class B : public A
{
public:
B (int x)
: A(x) // init
{
}
};
void doSomething()
{
try
{
throw - 1;
}
catch (...)
{
cout << "catch in doSomething()" << endl;
}
}
int main(void)
{
try
{
// doSomething()
B b(0);
}
catch (...)
{
cout << "catch in main(void)" << endl;
}
return (0);
}
14.6異常処理のリスクと欠点
#include <iostream>
using namespace std;
class Exception
{
public:
void report()
{
cerr << "Exception report" << endl;
}
};
class ArrayException : public Exception
{
public:
void report()
{
cerr << "Array exception" << endl;
}
};
class MyArray
{
private:
int m_data[5];
public:
int &operator [] (const int &index)
{
if (index < 0 || index >= 5) throw ArrayException();
return (m_data[index]);
}
};
void doSomething()
{
MyArray my_array;
try
{
my_array[100];
}
catch (const int &x)
{
cerr << "exception" << x << endl;
}
catch (ArrayException &e)
{
e.report();
throw e; // rethrow
// throw; // 객체 잘림 발생하지 않음
}
catch (Exception &e)
// catch (Exception &e)이 먼저 작성되어 있다면
// 받는 쪽에서 ArrayException이 아닌 Exception으로 받기 때문에
// 객체잘림과 유사하게 Exception report 출력
{
e.report();
}
}
int main(void)
{
try
{
doSomething();
}
catch(ArrayException &e)
{
cout << "main()" << endl; // rethrow 한것을 받는다
e.report();
}
return (0);
}
異なる状況に対する異常処理は
std::exception
によって実現された.それをどのように利用するかを理解してみましょう.#include <iostream>
#include <exception> // <-
#include <string>
class CustomException : public std::exception
{
public:
const char *what() const noexcept override
{
return ("Custom exception");
}
};
int main(void)
{
try
{
throw std::runtime_error("Bad thing happend");
}
catch (std::length_error &exception)
{
std::cerr << exception.what() << std::endl;
}
catch (std::exception &exception)
{
std::cerr << exception.what() << std::endl;
}
return (0);
}
14.5関数try #include <iostream>
using namespace std;
class A
{
private:
int m_x;
public:
A(int x) : m_x(x)
{
if (x <= 0)
throw 1;
}
B(int x) try : A(x)
{
// do init
}
catch (...)
{
cout << "catch in B constructor " << endl;
// throw; // 없어도 있는것처럼 작동!
}
};
class B : public A
{
public:
B (int x)
: A(x) // init
{
}
};
void doSomething()
{
try
{
throw - 1;
}
catch (...)
{
cout << "catch in doSomething()" << endl;
}
}
int main(void)
{
try
{
// doSomething()
B b(0);
}
catch (...)
{
cout << "catch in main(void)" << endl;
}
return (0);
}
14.6異常処理のリスクと欠点
#include <iostream>
using namespace std;
class A
{
private:
int m_x;
public:
A(int x) : m_x(x)
{
if (x <= 0)
throw 1;
}
B(int x) try : A(x)
{
// do init
}
catch (...)
{
cout << "catch in B constructor " << endl;
// throw; // 없어도 있는것처럼 작동!
}
};
class B : public A
{
public:
B (int x)
: A(x) // init
{
}
};
void doSomething()
{
try
{
throw - 1;
}
catch (...)
{
cout << "catch in doSomething()" << endl;
}
}
int main(void)
{
try
{
// doSomething()
B b(0);
}
catch (...)
{
cout << "catch in main(void)" << endl;
}
return (0);
}
throw
はタブーとされている.→ runtime error! throw
)メモリが自動的に解放されます.#include <iostream>
#include <memory>
using namespace std;
class A
{
public:
~A()
{
throw "error"; // <-
}
};
int main(void)
{
try
{
int *i = new int[10000000];
unique_ptr<int> up_i(i); // <-
// do something with i
throw "error";
// delete[] i;
// A a;
}
catch (...)
{
cout << "catch" << endl;
}
return (0);
}
Reference
この問題について([大杯C++14例外処理), 我々は、より多くの情報をここで見つけました https://velog.io/@24siefil/따배C-14.-예외처리テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol