[C++] 17. μμΈμ²λ¦¬(Exception), std::exception
μμΈμ²λ¦¬(Exception)
C++μμ μμΈμ²λ¦¬λ νλ‘κ·Έλ¨μ μ€ν μ€μ λ°μνλ μμΈ μν©μ κ°μ§νκ³ μ μ ν μ‘°μΉλ₯Ό μ·¨νλ λ©μ»€λμ¦μ λλ€. μ΄λ₯Ό ν΅ν΄ νλ‘κ·Έλ¨μ μμ μ±μ λμ΄κ³ μμμΉ λͺ»ν λ¬Έμ μ λμ²ν μ μκ² λ©λλ€. μμΈλ μΌλ°μ μΌλ‘ νλ‘κ·Έλ¨μ΄ μ€ν μ€μ λ°μνλ μ€λ₯ λλ μμμΉ λͺ»ν μν©μ λνλ λλ€. μ΄λ¬ν μν©μ μ²λ¦¬νλ λ° μ¬μ©λλ κΈ°λ³Έμ μΈ C++ μμΈ μ²λ¦¬ λ©μ»€λμ¦μ λν΄ μμλ³΄κ² μ΅λλ€.
μμΈ λμ§κΈ° (Throwing Exceptions)
μμΈλ₯Ό λμ§ λλ throw ν€μλλ₯Ό μ¬μ©ν©λλ€.
throw ν€μλ λ€μλ μμΈ κ°μ²΄κ° μ΅λλ€. μΌλ°μ μΌλ‘ μμΈ κ°μ²΄λ κΈ°λ³Έ λ°μ΄ν° νμ
μ΄λ μ¬μ©μ μ μ ν΄λμ€ κ°μ²΄μΌ μ μμ΅λλ€.
void doSomething(int value) {
if (value < 0) {
throw "Value cannot be negative!"; // λ¬Έμμ΄μ μμΈλ‘ λμ§
}
}
μμΈ λ€μ λμ§κΈ° (Rethrowing Exceptions)
ν¨μ λ΄λΆμμ μ²λ¦¬ν μμΈλ₯Ό μΈλΆλ‘ λ€μ λμ§ μ μμ΅λλ€. μ΄λ₯Ό μμΈ λ€μ λμ§κΈ°λΌκ³ ν©λλ€.
μ΄λ μ€μ²©λ try-catch λΈλ‘μμ μ¬μ©λλ©°, νμ¬ ν¨μμ catch λΈλ‘μ΄ μμΈλ₯Ό μ²λ¦¬ν μ μλ κ²½μ° μμ νΈμΆμλ‘ μμΈλ₯Ό μ λ¬νλ λ° μ¬μ©λ©λλ€.
void doSomething() {
try {
// μμ
μν
} catch (const SomeException& e) {
// μμΈ μ²λ¦¬
throw; // νμ¬ μμΈλ₯Ό λ€μ λμ§
}
}
μ¬μ©μ μ μ μμΈ ν΄λμ€ (Custom Exception Classes)
C++μμλ κΈ°λ³Έ λ°μ΄ν° νμ μΈμλ μ¬μ©μ μ μ μμΈ ν΄λμ€λ₯Ό λ§λ€μ΄ μμΈλ₯Ό λμ§ μ μμ΅λλ€. λ³΄ν΅ μ¬μ©μ μ μ μμΈ ν΄λμ€λ std::exception ν΄λμ€λ₯Ό μμλ°μμ μμ±ν©λλ€.
class MyException : public std::exception {
public:
const char* what() const noexcept override {
return "This is a custom exception!";
}
};
void doSomething() {
throw MyException();
}
std::exception
C++ νμ€ λΌμ΄λΈλ¬λ¦¬μμλ μμΈ μ²λ¦¬λ₯Ό μν΄ std::exception ν΄λμ€λ₯Ό μ 곡ν©λλ€. μ΄ ν΄λμ€λ C++ νμ€ μμΈ ν΄λμ€λ€μ κΈ°λ³Έ ν΄λμ€λ‘ μ¬μ©λ©λλ€. std::exception ν΄λμ€λ <exception> ν€λ νμΌμ μ μλμ΄ μμΌλ©°, λ€λ₯Έ μμΈ ν΄λμ€λ€μ μ΄ ν΄λμ€λ₯Ό μμλ°μ ꡬνλ©λλ€.
std::exception ν΄λμ€λ κ°μ₯ κ°λ¨ν μμΈ μ²λ¦¬λ₯Ό μν κΈ°λ° ν΄λμ€λ‘μ, μΌλ°μ μΌλ‘ μμΈμ λν μ 보λ₯Ό μ 곡νκΈ° μν΄ what() λ©€λ² ν¨μλ₯Ό κ°μ§κ³ μμ΅λλ€. μ΄ ν¨μλ μμΈμ λν μ€λͺ
μ C μ€νμΌμ λ¬Έμμ΄λ‘ λ°ννλ©°, νμ ν΄λμ€λ€μ μ΄ λ©€λ² ν¨μλ₯Ό μ€λ²λΌμ΄λνμ¬ μμ λ§μ μμΈ μ 보λ₯Ό λ°νν μ μμ΅λλ€.
std::exceptionμ μ μλ λ€μκ³Ό κ°μ΅λλ€:
namespace std {
class exception {
public:
exception() noexcept;
exception(const exception&) noexcept;
exception& operator=(const exception&) noexcept;
virtual ~exception();
virtual const char* what() const noexcept;
};
}
what() λ©€λ² ν¨μ
const char* what() const noexcept
μ΄ ν¨μλ μμΈμ λν μ€λͺ μ λ°νν©λλ€. κΈ°λ³Έμ μΌλ‘ μ΄ ν¨μλ "std::exception"μ λ°ννμ§λ§, νμ ν΄λμ€μμ μ΄ ν¨μλ₯Ό μ€λ²λΌμ΄λνμ¬ λ ꡬ체μ μΈ μ 보λ₯Ό μ 곡ν μ μμ΅λλ€.
#include <iostream>
#include <exception>
class MyException : public std::exception {
public:
const char* what() const noexcept override {
return "This is a custom exception!";
}
};
int main() {
try {
throw MyException();
} catch (const std::exception& e) {
std::cout << "Caught exception: " << e.what() << std::endl;
}
return 0;
}
// μΆλ ₯:
// Caught exception: This is a custom exception!
std::exception ν΄λμ€λ₯Ό μ§μ μ¬μ©ν기보λ€λ, μ΄λ₯Ό μμλ°μμ μ¬μ©μ μ μ μμΈ ν΄λμ€λ₯Ό λ§λ€μ΄μ λ ꡬ체μ μΈ μμΈ μ 보λ₯Ό μ 곡νλ κ²μ΄ μΌλ°μ μ λλ€. μ΄λ κ² ν¨μΌλ‘μ¨ μμΈ μ²λ¦¬ μ½λμμ λ μ μ©ν μ 보λ₯Ό μ»μ μ μκ² λ©λλ€.
μμΈλ₯Ό λ€μνκ² μ²λ¦¬νκΈ°
μμΈμ²λ¦¬λ μμ€ν μμΈ μ²λ¦¬ μμκ³Ό Standard libraryμ μμΈ μ²λ¦¬ μμμΌλ‘ λλ μ μμ΅λλ€. μ°λ¦¬κ° μ½λλ₯Ό μ§λ©΄μ λ°μ ν μ μλ λͺ¨λ μλ¬μ λν΄ μμΈμ²λ¦¬λ₯Ό ν μ μμ΅λλ€. κ·Έλ μ§λ§ λ€μν μμκ³Ό 쑰건μ κΈ°μ€μΌλ‘ μμΈλ₯Ό μ μνλ€λ©΄ μμΈλ₯Ό λ§μ£Όνμ λ λμ± μ μ°νκ² λμ²ν μ μμ κ²μ λλ€.
λ€μν μμΈ μ ν μ μνκΈ°
μ¬λ¬ μ’ λ₯μ μμΈλ₯Ό λ€λ£¨μ΄μΌ νλ κ²½μ°, κ°κ°μ μν©μ μ ν©ν μ¬μ©μ μ μ μμΈ ν΄λμ€λ₯Ό λ§λ€μ΄μ μ¬μ©ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ μμΈμ μ νμ λͺ ννκ² κ΅¬λΆνκ³ κ΅¬μ²΄μ μΈ μμΈ μ²λ¦¬λ₯Ό μνν μ μμ΅λλ€.
class FileOpenException : public std::exception {
public:
const char* what() const noexcept override {
return "Failed to open the file!";
}
};
class DivideByZeroException : public std::exception {
public:
const char* what() const noexcept override {
return "Division by zero is not allowed!";
}
};
μμΈ λ°μ 쑰건 λΆλ¦¬νκΈ°
μ¬λ¬ κ³³μμ μμΈκ° λ°μν μ μλ κ²½μ°, μμΈκ° λ°μνλ 쑰건μ λΆλ¦¬ν΄μ μ²λ¦¬ν μ μμ΅λλ€. μ΄λ κ² νλ©΄ μμΈ μ²λ¦¬ μ½λλ₯Ό κ°κ°μ μ μ ν μμΉμ λμ΄ μ½λμ κ°λ μ±μ λμΌ μ μμ΅λλ€.
void divideNumbers(int a, int b) {
if (b == 0) {
throw DivideByZeroException();
}
// λλ¨Έμ§ μ°μ° μν
}
void readFile(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
throw FileOpenException();
}
// νμΌ μ½κΈ° μν
}
μμΈ μ²λ¦¬μ 리μμ€ κ΄λ¦¬
리μμ€ κ΄λ¦¬λ μμΈ μμ μ±κ³Ό λ°μ ν κ΄λ ¨μ΄ μμ΅λλ€. μμΈκ° λ°μνλλΌλ μμμ΄ μ¬λ°λ₯΄κ² κ΄λ¦¬λλλ‘ μ€λ§νΈ ν¬μΈν°μ RAII(Resource Acquisition Is Initialization)λ₯Ό νμ©νλ κ²μ΄ μ’μ΅λλ€.
void someFunction() {
std::unique_ptr<int> ptr(new int(42)); // μ€λ§νΈ ν¬μΈν°λ‘ μμμ ν λΉ
// μμ
μν
// μμΈκ° λ°μνλλΌλ ptrμ΄ μλμΌλ‘ λ©λͺ¨λ¦¬λ₯Ό ν΄μ ν¨
}
μμΈ μμ μ±κ³Ό νΈλμμ
μμΈ μ²λ¦¬λ νΈλμμ κ³Ό μ μ¬ν κ°λ μ μ μ©ν μ μμ΅λλ€. μμΈκ° λ°μνλ©΄ ν΄λΉ μμ μ΄ λ‘€λ°±λλλ‘ κ΅¬ννμ¬ νλ‘κ·Έλ¨μ μΌκ΄μ±μ μ μ§ν μ μμ΅λλ€.
class BankAccount {
private:
int balance;
public:
void deposit(int amount) {
// μμΈ λ°μ μ μμ λ³μμ κΈ°μ‘΄ μμ‘μ μ μ₯νμ¬ λ‘€λ°± κ°λ₯νκ² ν¨
int tempBalance = balance;
try {
// μμ‘ λ³κ²½ μμ
μν
balance += amount;
} catch (...) {
// μμΈ μ²λ¦¬ ν μμ‘μ μ΄μ κ°μΌλ‘ λ‘€λ°±
balance = tempBalance;
throw; // μμΈλ₯Ό λ€μ λμ Έμ μμ νΈμΆμμκ² μ ν
}
}
};