MoreEffectiveC++
1.1. Item 9: Use destuctors to prevent resource leaks. ¶
- Item 9: μμμ΄ μλκ±Έ λ§λ νκ΄΄μλ₯Ό μ¬μ©ν΄λΌ.
ALAλ (Adorable Little Animalμ΄λ€.)
~cpp class ALA{ publid: virtual void processAdiption() = 0; ... }; class Puppy: public ALA{ publid: virtual void processAdiption(); ... }; class Kitten: pubic ALA{ publid: virtual void processAdiption(); ... };
μΌλ¨ μ¬λ¬λΆμ νμΌμμ λΆν° puppyμ kittenμ ν€νΌμ μ 보λ₯Ό μ΄λ κ² μ½κ³ λ§λ λ€. μ¬μ€ Item 25μ μΈκΈν virtual constructorκ° μ 격μ΄μ§λ§, μΌλ¨ μ°λ¦¬μ λͺ©μ μ λ§λ ν¨μλ‘ λ체νλ€.
~cpp ALA * readALA(istream& s);
λ€μκ³Ό κ°μ λλ(?)μΌλ‘ μΆλ ₯νλ€.
~cpp void processAdoptions( istream& dataSource) { while (dataSource) { ALA *pa = readALA(dataSource); pa->processAdoption(); delete pa; } }paμ ν΄λΉνλ processAdoption()μ μ€λ₯μμ exceptionμ λμ§λ€. νμ§λ§, exceptionμμ ν΄λΉ μ½λκ° λ©μΆλ€λ©΄ "delete pa;"κ° μνλμ§ μμμ κ²°κ΅ μμμ΄ μλ ν¨κ³Όκ° μκ² μ§ κ·Έλ λ€λ©΄ λ€μκ³Ό κ°μ΄ μΌλ¨ μμΈ μ²λ¦¬λ₯Ό νλ€. λ¬Όλ‘ ν΄λΉ ν¨μμμ propagateν΄μ£Όμ΄ ν¨μ μ체μμλ μμΈλ₯Ό λ°μ μν¨λ€.
~cpp void processAdoptions( istream& dataSource) { while (dataSource) { ALA *pa = readALA(dataSource); try{ pa->processAdoption(); } catch ( ... ) { delete pa; throw; } delete pa; } }
λ°©λ²μ μ¬λ°λ₯΄λ€. μμΈμμ ν΄λΉ κ°μ²΄λ₯Ό μ§μ λ²λ¦¬λκ², κ·Έλ¦¬κ³ μ΄κ±΄ μ°λ¦¬κ° λ°°μ΄ try-catch-throwλ₯Ό μΆ©μ€ν μ¬μ©ν κ²μ΄λ€. νμ§λ§.. 볡μ‘νμ§ μμκ°? ν΄λΉ μ½λλ λ§κ·Έλλ‘ νΌμ³μ§λ€.(μμμ νν) κ·Έλ¦¬κ³ μ½λμ κ°λ
μ±λ λ¨μ΄μ§λ©°, μ°¨ν κ΄λ¦¬ μ°¨μμμ μΆκ° μ½λμ λ°μμμλ μ΄λ μμμ 보κ°ν κ² μΈκ°μ κ΄νμ¬ λ¬Έμ μ λλ€.
μ¬κΈ°μμ μ¬λ―Έμλ κΈ°λ²μ μ΄μΌκΈ° ν΄λ³Έλ€. μ°¨μ°¨ μκ°λ smart pointerμ λλΆμ΄ Standard C++ λΌμ΄λΈλ¬λ¦¬μ ν¬ν¨λμ΄ μλ auto_ptr template ν΄λμ€λ₯Ό μ΄μ©ν ν΄κ²°μ±
μΈλ° auto_prtμ μ΄λ κ² μκ²Όλ€.
~cpp template<class T> class auto_ptr{ public: auto_ptr(T *p = 0) : ptr(p) {} private: T *ptr; };
κ·Έλ¦¬κ³ ν΄λΉ auto_prtμ μ μ©ν λͺ¨μ΅μ λ€μκ³Ό κ°μ΄ 보μΈλ€.
~cpp void processAdoptions(istream& dataSource) { while (dataSource){ auto_ptr<ALA> pa(readALA(dataSource)); pa->processAdoption(); } }
μμΈ λ°μμμ ν¨μκ° μ’
λ£λλ©΄ auto_ptrμμ κ°μ²΄λ 무쑰건 ν΄μ λλ€.
μμ λ€μ μ½λλ μμμ΄ μ
κ²μ΄λ€.
~cpp void displayIntoInfo(const Information& info) { WINDOW_HANDLE w(createWindow()); display info in window corresponding to w; destroyWindow(w); }
μΌλ°μ μΌλ‘ Cμ κ°λ
μΌλ‘ μ§μ¬μ§ νλ‘κ·Έλ¨λ€μ createWindow and destroyWindowμ κ°μ΄ κ΄λ¦¬νλ€. κ·Έλ μ§λ§ μ΄κ² μμ destroyWindow(w)μ λλ¬μ μ μμΈ λ°μμ μμμ΄ μΈλ κ²½μ°κ° μκΈ΄λ€. κ·Έλ λ€λ©΄ λ€μκ³Ό κ°μ΄ λ°κΎΈμ΄μ ν΄λ³Έλ€.
~cpp class WidnowHandle{ public: WindowHandle(WINDOW_HANDLE handle) : w(handle) {} ~WindowHandle() {destroyWindow(w); } operator WINDOW_HANDLE() {return w;} private: WINDOW_HANDLE w; WindowHandle(const WindowHandle&); WindowHandle& operator=(const WindowHandle);
auto_ptrκ³Ό κ°μ μ리μ΄λ€.
~cpp void displayIntoInfo(const Information& info) { WINDOW_HANDLE w(createWindow()); display info in window corresponding to w; }
1.2. Item 10: Prevent resource leaks in constructors. ¶
- Item 10: μμ±μμμ μμμ΄ μΈλκ±Έ λ§μλΌ.
~cpp class Image{ public: Image(const string& imageDataFileName); ... }; class AudioClip{ public: AudioClip(const string& audioDataFileName); ... } class PhoneNumber{ ... }; class BookEntry{ public: BookEntry(const string& name, const string& address = "", const string& imageFileName = "", const string& audioClipFileName = ""); ~BookEntry(); void addPhoneNumber(const PhoneNumber& number); private: string the Name; string the Address; list<phoneNumber> thePhones; Image *theImage; AudioClip *theAudioClip; };
κ°κ°μ BookEntryλ μ΄λ¦κ³Ό λλΆμ΄ λ€λ₯Έ νλλ₯Ό κ°μ§κ³ μμΌλ©° κΈ°λ³Έ μμ±μλ λ€μκ³Ό κ°λ€.
~cpp // κΈ°λ³Έ μμ±μ BookEntry::BookEntry(const string& name, const string& address, const string& imageFileName, const string& audioClipFileName) :theName(name), theAddress(address), theImage(0), theAudioClip(0) { if (imageFileName != ""){ // μ΄λ―Έμ§λ₯Ό μμ±νλ€. theImage = new Image(imageFileName); } if (audioClipFileName != "") { // μ리 μ 보λ₯Ό μμ±νλ€. theAudioCilp = new AudioClip( audioClipFileName); } } BookEntry::~BookEntry() { delete theImage; delete theAudioClip; }
μμ±μλ theImageμ theAudioClipλ₯Ό nullλ‘ μ΄κΈ°ν μν¨λ€. C++μμμ nullκ°μ΄λ deleteμμμμ μμ μ 보μ₯νλ€. νμ§λ§... μμ μ½λμ€μ λ€μ μ½λμμ newλ‘ μμ±ν μμ μμΈκ° λ°μλλ€λ©΄?
~cpp if (audioClipFileName != "") { theAudioClip = new AudioClip(audioClipFileName); }
μμ μλ₯Όλ€μ΄μ μ΄λ° ν¨μμμ μμΈ μ²λ¦¬λ₯Ό ν΄μΌν κ²μ΄λ€.
~cpp void testBookEntryClass() { BookEntry b( "Addison-Wesley Publishing Company", "One Jacob Way, Reading, MA 018678"); ... }
μ΄λ κ² try-catch-throwλ‘ λ§μ΄λ€.
~cpp void testBookEntryClass() { BookEntry *pb = 0; try{ pb = new BookEntry( "Addison-Wesley Publishing Company", "One Jacob Way, Reading, MA 018678"); } catch ( ... ) { delete pb; throw; } delete pb; }
μ΄λ κ² ν΄λ μ¬μ ν λ¬Έμ λ λ¨λλ€. 무μμ΄λ νλ©΄, λ§μ½ BookEntryμ μμ±μμ€μμ AudioClip κ°μ²΄ μμ±μ€μ μμΈλ₯Ό propagateνλ©΄ λ°λ‘ μ μ½λμ€ pb ν¬μΈν°μ nullμ λ°νν΄ λ²λ¦°λ€. λ°λ©λ μ΄λ κ² λλ©΄ μ΄λ―Έ μ μμ μΌλ‘ μμ±λ theImageλ₯Ό μ§μ°μ§ λͺ»νλ μ¬νκ° λ°μν΄ λ²λ¦¬λ κ²μ΄λ€.
κ·Έλ λ€λ©΄ μμ±μμ λ΄λΆμμ λ€μ try-catch-throwλ‘ ν΄μΌ ν κ²μ΄λ€.
~cpp BookEntry::BookEntry(const string& name, const string& address, const string& imageFileName, const string& audioClipFileName) :theName(name), theAddress(address), theImage(0), theAudioClip(0) { try{ if (imageFileName != ""){ theImage = new Image(imageFileName); } if (audioClipFileName != "") { theAudioCilp = new AudioClip( audioClipFileName); } } catch (...){ delete theImage; delete theAudioClip; throw; } }
μ μ΄λ κ² ν΄μ£Όλ©΄ λ¬Έμ λ κ²μ΄ μλ€. μ μ΄μνμ refactoringμ΄ νμν μ½λλ€μ΄ 보μΌκ²μ΄λ€ νκ² λ€. deleteλΆλΆμ ν¨μλ‘ μμ΄ λ€λ κ²μ΄λ€.
~cpp class BookEntry{ public: ... private: ... void cleanup(); // μ΄κ²μ΄ κ°μ²΄λ₯Ό μμ νλκ±Έ λ¬Άμκ² };
~cpp BookEntry::BookEntry(const string& name, const string& address, const string& imageFileName, const string& audioClipFileName) :theName(name), theAddress(address), theImage(0), theAudioClip(0) { try{ ... } catch (...){ cleanup(); throw; } } BookEntry::~BookEntry{ cleanup(); }
μ μ΄μ κΉ¨λμ΄ ν΄κ²° λ κ²μΌλ‘ 보μΈλ€. νμ§λ§ μ΄λ²μλ μ΄λ° κ²½μ°λ₯Ό μμ ν΄ λ³΄μ
~cpp class BookEntry{ public : ... private: ... Image * const theImage; AudioClip * const theAudioClip; }
μ΄λ° const ν¬μΈν°μ κ²½μ°μλ λ°λμ μ΄κΈ°ν 리μ€νΈλ₯Ό μ΄μ©νμ¬ μΈμλ₯Ό μ΄κΈ°ν ν΄μ£Όμ΄μΌ νλ κ²½μ°μ΄λ€.
~cpp class BookEntry{ public : ... private: ... Image * initImage(const string& imageFileName); AudioClip * initAudioClip(const string& theAudioClip); } BookEntry::BookEntry(const string& name, const string& address, const string& imageFileName, const string& audioClipFileName) :theName(name), theAddress(address), theImage(initImage(imageFileName)), theAudioClip(initAudioClip(AudioCilpFileName)) {} // theImageλ κ°μ₯ μ²μ μ΄κΈ°ν λμ΄μ μμμ΄ μΈλ κ²μλν κ±±μ μ΄ μλ€. κ·Έλμ ν΄λΉ μμ€μμ // μμΈμ²λ¦¬λ₯Ό μλ΅νμλ€. Image * initImage(const string& imageFileName) { if (imageFileName != "") return new Image(imageFileName); else return 0; } // theAudioClipλ λλ²μ§Έλ‘ μ΄κΈ°ν λκΈ° λλ¬Έμ, μμΈμ λ°μκ²½μ° μ΄λ―Έ ν λΉλμ΄μ§ theImageμ μμμ // ν΄μ ν΄μ£Όλ μμΈ μ²λ¦¬κ° νμνλ€. AudioClip * initAudioClip(const string& theAudioClip) { try{ if (adioClipFileName != ""){ return new AudioClip(audioClipFileName); } else return 0; } catch ( ... ){ delete theImage; throw; } }
μ΄λ° ν΄κ²° λ°©λ²μ μ¬λ°λ₯΄λ€ νμ§λ§, μ΄μ μ μΈκΈν κ²κ³Ό κ°μ΄ μμ€ μ¬ν κ΄λ¦¬μ νμ¬ μμ€ μ체λ λ§μ΄ μ§μ λΆνλ€
κ·Έλμ λ μ’μ λ°©λ²μ Item 9μμ μΈκΈν λ°©λ²μ μ¬μ©νλ κ²μ΄λ€.
~cpp class BookEntry{ pubcli: ... private: ... const auto_ptr<Image> theImage; const auto_ptr<AudioClip> theAudioClip;κ·Έλ¦¬κ³ μμ±μμ μ½λλ₯Ό μ΄λ κ² νλ€.
~cpp BookEntry::BookEntry(const string& name, const string& address, const string& imageFileName, const string& audioClipFileName) :theName(name), theAddress(address), theImage(imageFileName != "" ? new Image(imageFileName) : 0), theAudioClip( audioClipFileName != "" ? new AudioClip(audioClipFileName):0) {}
μ΄λ κ² λμμΈ ν κ²½μ° νκ΄΄λ μλμΌλ‘ μ΄λ£¨μ΄ μ§λ€. κ·Έλ¬λ―λ‘ νκ΄΄μλ
~cpp BookEntry::~BookEntry() {}μ΄λ κ² μ무κ²λ ν΄μ£Όμ§ μμλ κ°μ²΄κ° κ°μ΄ νκ΄΄λκ³ λ¦¬μμ€κ° μλ κ²μ λ°©μ§ ν μ μλ€.
1.3. Item 11: Prevent exception from leaving destuctors. ¶
- Item 11: νκ΄΄μλ‘ λΆν°μ μμΈ μ²λ¦¬λ₯Ό λ§μλΌ.
λ€μ μμ λ online μ»΄ν¨ν° μΈμ
μ μν Session ν΄λμ€λ₯Ό μκ°ν΄ λ³Έ κ²μ΄λ€. κ° μΈμ
κ°μ²΄λ€μ μμ±κ³Ό νλλ λ μ§λ₯Ό κΈ°λ‘ν΄μΌλ§ νλ€.
~cpp class Session{ public: Session(); ~Session(); ... private: static void logCreation(Session *objAddr); static void logDestruction(Session *objAddr); };
λ€μκ³Ό κ°μ΄ νκ΄΄μμμ λ‘κ·Έ λ°μ΄ν°λ₯Ό λ¨κΈ΄λ€.
~cpp Session::~Session() { logDestruction(this); }
μ μ΄κ±΄ κ΄μ°μ 보μΈλ€. νμ§λ§ μ logDestructionμμμ μμΈκ° λ°μνλ€λ©΄ μ΄μ©κ² ν κ²μΈκ°? ν΄λΉ μμ€λ Sessionμ νκ΄΄μ μμμλ μμΈλ₯Ό μ‘μ§ λͺ»νλ€. κ·Έλμ ν΄λΉ νκ΄΄μλ₯Ό νΈμΆν μμκ² μμΈλ₯Ό λμ§(μ λ¬ν)λ€. κ·Έλ μ§λ§ λ€λ₯Έ μλ¬λ€μ΄ λμ Έμ§ μν©μμ νκ΄΄μκ° μ€μ€λ‘ μμ μ λΆλ₯Έκ±°λΌλ©΄ ν¨μμ μ’
λ£κ° μλμΌλ‘ μ΄λ£¨μ΄μ§κΈ°λ₯Ό μν κ²μ΄λ€. κ·Έλ¦¬κ³ λΉμ μ νλ‘κ·Έλ¨μ μ΄μ―€μμ λ¨ΈμΆμ΄ λ²λ¦΄ κ²μ΄λ€. -ν΄μμ΄ μ΄μνκ΅°, μνΌ λ€λ₯Έ μμΈ μ²λ¦¬μμ μΈμ
νκ΄΄μ λ‘κ·Έμ μμΈκ° λ°μνλ€λ©΄ νλ‘κ·Έλ¨μ΄ λ©μΆλ€λ μ리λ€.
μλ§ λλ€μμ μ¬λλ€μ΄ μ΄λ° μνλ‘ λΉ μ§λκ±Έ μνμ§ μμ κ²μ΄λ€. Session κ°μ²΄μ νκ΄΄λ κΈ°λ‘λμ§ μμ νλκΉ. 그건 μλΉν 컀λ€λ λ¬Έμ μ΄λ€ κ·Έλ¬λ κ·Έκ²μ΄ μ’λ μ¬ν λ¬Έμ λ₯Ό μ λ°νλ건 νλ‘κ·Έλ¨μ΄ λ μ§ν μ μμ λ μΌκ²μ΄λ€. κ·Έλμ Sessionμ νκ΄΄μμμμ μμΈ μ λ¬μ λ§μμΌ νλ€. λ°©λ²μ νλ try-catchλ‘ μ‘μ λ²λ¦¬λ κ²μ΄λ€.
~cpp Session::~Sessioni() { try{ logDestruction(this); } catch ( ... ){ cerr << "ν΄λΉ μ£Όμμμ μΈμ κ°μ²΄μ νκ΄΄κΈ°λ‘μ΄ λμ§ μμ΅λλ€." << "-μ£Όμ:" << this << ".\n"; }νμ§λ§ μ΄κ²λ μλμ μ½λλ³΄λ€ μμ ν κ²μ΄ μλ€. λ§μ½ operator<< λΆλ₯Όλ exceptionμ΄ λ°μνλ€λ©΄ νκ΄΄μκ° λμ§λ exceptionμΌλ‘ λ€μ μ°λ¦¬κ° ν΄κ²°νκ³ μ νλ μμ μΌλ‘ λμκ° λ²λ¦°λ€. κ·Έλ λ€λ©΄
~cpp Session::~Sessioni() { try{ logDestruction(this); } catch ( ... ){ }μ΄λ κ² μλ¬΄λ° μ²λ¦¬λ₯Ό νμ§ μλλ€λ©΄ logDestuctionμμ λ°μν μμΈκ° μ λ¬λλκ±Έ λ§κ³ νλ‘κ·Έλ¨ μ€μ§λ₯Ό μνμ¬ μ€νμ΄ νλ €λκ°λκ±Έ λ§μμλ μμ κ²μ΄λ€.
νμ§λ§ μ΄λ° λλ²μ§Έμ μκ°λ νκ΄΄μμμ λ°μνλ λͺ¨λ μλ¬λ₯Ό λ§μ λ²λ¦¬κ³ κ·Έλ₯ λμ΄κ° λ²λ¦°λ€λ λ¨μ μ΄ μλ€.
λ°μ μ½λλ DBμ νΈλμ μ μ μ΄μ©ν΄μ μλ¬λ₯Ό μ²λ¦¬νλ λͺ¨μ΅μ΄λ€.
λ°μ μ½λλ DBμ νΈλμ μ μ μ΄μ©ν΄μ μλ¬λ₯Ό μ²λ¦¬νλ λͺ¨μ΅μ΄λ€.
~cpp Session::Session() { logCreation(this); startTransaction(); } Session::~Session() { logDestruction(this); endTransaction(); }μ΄λ΄ κ²½μ°μλ Sessionμ νκ΄΄μμκ² λ¬Έμ λ₯Ό μ κ±°νλ λͺ λ Ήμ λ€μ λ΄λ¦΄μ μλ° νμ§λ§ endTransactionμ΄ μμΈλ₯Ό λ°μνν¨λ€λ©΄ λ€μ try-catchλ¬ΈμΌλ‘ λμ κ°μ λ°μ μλ€.
λμ λ€ λμ
1.4. Item 12: Understand how throwing an exception differs from passing a parameter or calling a virtual function ¶
- Item 12: κ°μ ν¨μ λΆλ₯΄κΈ°λ, μΈμ μ λ¬λ‘ μ²λ¦¬μ μμΈμ λ¬μ λ°©λ²μ μ°¨μ΄μ μ μ΄ν΄νλΌ.
~cpp class Widget { ... }; void f1(Widget w); void f2(Widget& w); void f3(const Widget w); void f4(Widget *pw); void f5(const Widget *pw); catch (Widget w) ... catch (Widget& w) ... catch (const Widget w) ... catch (Widget *pw) ... catch (const Widget *pw) ...
κ·Έλμ μλ§ ν¨μνΈμΆμμ μΈμ μ λ¬κ³Ό κ³Ό μμΈκ° μ λ¬λλ κ²μ΄ κΈ°λ³Έμ μΌλ‘ κ°μκ²μ΄λΌκ³ μκ° ν μ§λ λͺ¨λ₯Έλ€. λΆλͺ
λμ λΉμ·ν λ©΄μ΄ μλ€. νμ§λ§ μ€μν μ°¨μ΄μ μμ μ‘΄μ¬ νλ€.
μ, λΉμ·ν λ©΄μ μΈκΈν΄λ³΄λ©΄, ν¨μ μμΈ λͺ¨λ μ μΈμλ₯Ό μ λ¬ν λ μΈκ°μ§λ‘ μ λ¬ν μ μλ€. κ°(by value)μ΄λ μ°Έμ‘°(by reference)λ, νΉμ ν¬μΈν°(by pointer)λ λ°λ‘ μ΄κ²μ΄λ€. νμ§λ§ μ΄ ν¨μμ μμΈμμμ μΈμμ μ λ¬ λ°©μμ ꡬλ λ°©λ²μμ κ²°μ μ μΈ μ°¨μ΄μ μ 보μΈλ€. μ΄λ° μ°¨μ΄μ μ λΉμ μ΄ ν¨μλ₯Ό νΈμΆν λ μ΅μ’
μ μΌλ‘ λ°νλλ κ°(returns)μ΄ ν΄λΉ ν¨μλ₯Ό λΆλ₯΄λ μμΉλ‘ κ°μ§λ§, μμΈμ κ²½μ°μ throwμ μμΉμ returnμ μμΉκ° λ€λ₯΄λ€λ μ μμ κΈ°μΈνλ€.
λ€μ ν¨μμμ Widgetμ μΈμ μ λ¬κ³Ό μμΈμμμ μ λ¬μ μκ°ν΄ 보μ.
~cpp // μ΄ μμ€λ μμ Widgetμ μΌνμ΄λΌκ³ μκ°νλ©΄ 무리 μκ² λ€. istream operator>>(istream& s, Widget& w); void passAndThrowWidget() { Widget localWidget; cin >> localWidget; throw localWidget; }
localWidgetμ΄ operator>> λ‘ μ λ¬λ λλ 볡μ¬μ κ³Όμ μ΄ μΌμ΄λμ§ μλλ€. λμ operator>> μμ μ°Έμ‘° wκ° localWidgetκ³Ό λ¬Άμ¬μ μ΄λ ν κ³Όμ μ μ²λ¦¬νκ² λλ€. νμ§λ§ μμΈμ μ²λ¦¬μμ localWidgetμ μ’ λ€λ₯Έ μ΄μΌκΈ°λ₯Ό λ§λ€μ΄ λκ°λ€. μμΈκ° κ°μ΄λ, μ°Έμ‘°λ₯Ό μ‘λ μ‘μ§(pointerλ μ‘μ§ λͺ»νλ€.) μλ μκ΄ μμ΄ localWidgetμ μ¬λ³Έμ΄ λ§λ€μ΄μ§κ³ , κ·Έ μ¬λ³Έμ catchλ‘ μ λγΉ λλ€. μλνλ©΄ passAndThrowWidgetμ μμμ λ²μ΄λλ©΄ localWidgetμ νκ΄΄μμ νΈμΆμ΄ λκΈ° λλ¬Έμ λ°λμ μ΄λ κ² λμ΄μΌ νλ€. μ΄κ²μ C++ μμ μμΈλ νμ μ¬λ³ΈμΌλ‘ μ λ¬λλ€λ μ΄μ κ° λλ€.
μ΄λ° 볡μ¬μ κ³Όμ μ μ무리 νκ΄΄μ μνμ΄ μλ μμΈλΌλ μ΄λ£¨μ΄ μ§λ€. μλ₯Ό λ€μλ©΄
~cpp void passAndThrowWidget() { static Widget localWidget; cin >> localWidget; throw localWidget; }
ν΄λΉ μ¬λ³Έμ κ΅¬μ§ λ³΅μ¬ν νμκ° μμ κ²μ΄λ€. νμ§λ§ catch λ 볡μ¬ν΄ λκ°κ³ κ·ΈλμΌλ§ catch μμ localWidgetμ μ¬λ³Έμ νΈμ§ν΄μ μ΄μ©ν μ μλ€. μ΄λ¬ν 볡μ¬μ κ·μΉμ ν¨μ μ λ¬κ³Ό μμΈ μΈμ μ λ¬μ μ°¨μ΄μ μ μ€λͺ
ν΄ μ€λ€.
κ°μ²΄κ° μμΈλ₯Ό μνμ¬ λ³΅μ¬κ° λ λ 볡μ¬λ ν΄λΉ κ°μ²΄μ 볡μ¬μμ±μ(copy constructor)μ μνμ¬ μν λλ€. μ΄ λ³΅μ¬μμ±μλ κ°μ²΄μ dynamicνμ΄ μλ static νμ ν΄λΉνλ ν΄λμ€μ€ νλμ΄λ€. κ°λ
μ νμΈμ μν΄ μ μμ€μ μμ λ²μ μ μκ°ν΄ 보μ
~cpp class Widget { ...} class SpecialWidget: public Widget { ... }; void passAndThrowWidget() { SpecialWidget localSpecialWidget; ... Widget& rw = localSpecialWidget; throw rw; // rwμ ν μ¦ Widgetμ 볡μ¬μμ±μκ° μλνμ¬ λ³΅μ¬ν΄ μμΈλ₯Ό λ°μμν¨λ€. }
λ€μμ κ²½μ° passAndThrowWidget μ΄ λμ§λ건 Widget μ΄λ€. μμμ μΈκΈνλ―μ΄ static typeμΌλ‘ μμΈλ μ λ¬λλ€. μ»΄νμΌλ¬λ rwκ° SpecialWidgetμΌλ‘μ λμμ μ ν μκ°νμ§ μλλ€.
μμΈμ²λ¦¬μμ λ€λ₯Έ κ°μ²΄μ μ¬λ³Έμ΄ μ λ¬ λλ€λ μ μ μμΈκ° κ³μ μ λ¬(νΌμ Έλκ°λ,propagate)μλ νκ°μ§μ κ³ λ €μ¬νμ΄ λ°μνλ€. λ€μμ λκ°μ§μ catch λΈλμ μ°¨μ΄μ μ΄ μλ€. νμ§λ§ μΈκ²¬μ κ°μ μν μ νλ€.
~cpp catch (Widget& w) { ... throw; // ν΄λΉ κ°μ²΄λ₯Ό λ€μ 볡μ¬νμ§ μκ³ λμ§λ©°, ν΄λΉ μμΈλ₯Ό propagete νλ€. } catch (Widget& w) { ... throw w; // ν΄λΉ κ°μ²΄λ₯Ό λ€μ 볡μ¬ν΄μ κ·Έ μ¬λ³Έμ propagateνλ€. }μ£Όμμ λμ΄ μλλ°λ‘, μκ°ν΄ 보λΌ. throwκ° λ³΅μ¬μμ±μλ₯Ό νΈμΆνμ§ μμμ ν¨μ¨μ μ΄λ€. κ·Έλ¦¬κ³ throwλ μ΄λ ν νμ΄λ μμΈλ₯Ό μ λ¬νλλ° μκ΄νμ§ μλλ€. νμ§λ§, μ¬μ€ μμΈμμ²΄κ° κ·Έ νμ λ§κ² λμ Έμ§λ―λ‘ κ±±μ μ΄ μλ€. νμ§λ§ catchλ¬Έμμ μμΈλ₯Ό λμ§λ κ°μ²΄μ ννλ₯Ό λ°κΏ νμμ±μ΄ μμλ νμλ₯Ό μ¬μ©ν΄μΌ κ² λ€.
μ κ·ΈλΌ λ€μμ μΈκ°μ§ catchμ κ΄ν΄μ μνν΄ λ³΄μ. passAndThrowWidgetμμ λ°μν μμΈλ λ€μμ μΈκ°μ§μ κ²½μ°λ‘ μ‘μμ μλκ±Έ μμν μ μλ€.
~cpp catch (Widget w) ... // κ°μΌλ‘ μ λ¬ catch (Widget& w) ... // μ°Έμ‘° μ λ¬ catch (const Widget& w) ... // μμ μ°Έμ‘°λ‘ μ λ¬μ λ¬λ κ°μ²΄λ κ°λ¨ν μ°Έμ‘°λ‘ μ‘μμ μλ€;κ·Έκ²μ μμ μ°Έμ‘°λ‘ μ λ¬λ νμμ±μ μλ€. κ·Έλ¬λ μμ μ°Έμ‘°κ° μλ μ λ¬ μμ κ°μ²΄λ€μ ν¨μλ₯Ό λΆλ₯΄λκ±Έ νμ©νμ§ μλλ€.
κ·ΈλΌ μ΄λ€μ μ°¨μ΄μ μ μ΄ν΄λ³΄κ³ μμΈ κ°μ²΄λ€μ 리ν΄ν΄ 보μ.
~cpp catch (Widget w) ... // κ°μΌλ‘ μ λ¬
μ΄λ κ² κ°μΌλ‘ μ λ¬νλ©΄ λλ²μ 볡μ¬κ° μΌμ΄λλκ±Έ μμν μ μλ€. throwμ νλ² catchμ νλ² ok? λΉν¨μ¨μ΄λ€.
μ°Έμ‘°λ‘ μ λ¬ν λ μμν΄ λ³΄μ
~cpp catch (Widget& w) ... // μ°Έμ‘° μ λ¬. catch (const Widget& w) ... // μμ-μ°Έμ‘° μ λ¬μ°λ¦¬λ μ§κΈκΉμ§ 볡μ¬μ μν μ§λΆμ μκ°ν μ μλλ° μ°Έμ‘°μ μ λ¬μ λ°λλ‘ λ³΅μ¬νλ μμ μ΄ μλ€. μ¦, νλ²μ λ³΅μ¬ μ΄ν κ³μ κ°μ κ°μ²΄λ₯Ό μ¬μ©νκ² λλ μ μ΄λ€.
μ°λ¦° μμ§ ν¬μΈν° μ λ¬μ μν κ±Έ μλ
Όνμ§ μμλ€. νμ§λ§ ν¬μΈν°λ₯Ό μ΄μ©ν΄ μμΈλ₯Ό λμ§(μ λ¬:throw)νλ κ²μ ν¨μμμμ ν¬μΈν°λ₯Ό μ λ¬(pass)νλ κ²κ³Όλ λ€λ₯Έκ±Έ μμ μμ κ²μ΄λ€. μ¦, ν¬μΈν°μ 볡μ¬λ³Έμ΄ μ΄λνλλ°, μ΄λ κ² λλ©΄ pointerλ₯Ό μ λ¬νλ μͺ½μ μμμμ throwμ μν΄ νμ΄ λκ°λ©΄ ν¬μΈν°κ° κ°λ¦¬ν€κ³ μλ κ°μ²΄λ μλ©Έλλ―λ‘ ν¬μΈν°μ μν μμΈ μ λ¬(λμ§λκ²:throw)λ νΌν΄μΌ νλ€. (μ μμ static κ°μ²΄μ ν¬μΈν°λΌλ©΄ μ΄μΌκΈ°λ λ¬λΌμ§λ€. λ€μ λ€λ£¬λ€.)
μ κ·ΈλΌ μμΈλ₯Ό λμ§λμ νμ κ΄ν μ£Όμλ₯Ό μ΄ν΄ 보μ. C++μ μμμ λ³νμ μν κ²μ΄ κ·Έ λ¬Έμ μ λ°λ¨μΈλ°, μ½λλ₯Ό 보μ νμ€ μν λΌμ΄λΈλ¬λ¦¬μμ
~cpp double sqrt(double);λ₯Ό μ΄λ κ² μ¬μ© ν μ μλ€.
~cpp int i; double sqrtOfi = sqrt(i);Item 5μλ μΈκΈλμ΄ μλ―μ΄ C++μμμμ μμμ λ³νμ κ΄ λ²μνλ€. iνμ doubleλ³νμ κ°λΏ? νλ€. νμ§λ§ λ€μμ 보μ
~cpp void f (int value) { try { if (someFunction() ) { // someFunction()μ΄ μ°Έμ΄λ©΄ intνμ λ³μλ₯Ό μμΈλ‘ λμ§λ€. throw value; } ... } catch (double d) { // ν΄λΉ νΈλ€μ doubleμΌλλ§ μμΈλ₯Ό μ‘μμ μλ€. κ·ΈλΌ valueλ₯Ό λμ§λ ... // tryμμμ μμΈλ μ λλ‘ μ‘νμ§ μλλ€. μλν λ°κ° μλ리λΌ. } ... }μ΄λ° μ¬νμ μ μ ν΄μΌ νλ€. μμΈμμλ μμμ λ³νμ μκ°νμ§ μλλ€.
κ·ΈλΌ μμΈμ λ³νμλ ν¬κ² λκ°μ§μ μκ°ν μ μ΄ μλλ°. 첫λ²μ§Έκ° μμ κ΄κ³(μμΈ μμ) μ΄λ€. μμΈμμλ ν μμΈ κ°μ²΄μμ νμλ λ€λ₯Έ μμΈκ°μ²΄λ€μ μ‘λκ²μ΄ κ°λ₯νλ° μλ₯Όλ€μ΄μ νμ€ C++ λΌμ΄λΈλ¬λ¦¬μμμ μμΈ μμλλ μ΄λ κ² κ΅¬μ±λμλ€. (λͺ¨λ μμΈκ° λμλμ§λ λͺ¨λ₯΄κ² λ€.)
~cpp exception | +-logic_error | | | +-domain_error | +-invalid_argument | +-length_error | +-runtime_error | +-range_error +-underflow_error +-overflow_error
catchμμ λΆλͺ¨ κ°μ²΄λ‘ μ‘μΌλ©΄ μμ κ°μ²΄μ μμΈλ€μ΄ λ€ μ‘νλ μμ΄λ€ .μλ₯Ό λ€μλ©΄
~cpp catch (runtime_error) ... // μ΄λ κ² μ μΈνλ©΄ runtime_errorμμμΈ catch (runtime_error&) ... // range_error, underflow_error catch (const runtime_error&) ... // overflow_errorμ΄ λ€ μ‘νλ κ±°λ€. catch (runtime_error*) ... // μ΄λ κ² νλ©΄ runtime_error* catch (const runtime_error*) ... // range_error*, underflow_error*, overflow_error* μΌλ‘ μ‘νλ κ²μ΄λ€.
λλ²μ§Έμ μκ°ν μ μ λͺ¨λ μμΈλ₯Ό μ‘κ³ μΆμΌλ©΄
~cpp catch (const void*) ...μ΄λ κ² νλ©΄ μ΄λ ν ν¬μΈν° typeλΌλ μ‘μ κ²μ΄λ€.
λ§μ§λ§μΌλ‘ μΈμ λκΈ°κΈ°μ μμΈ μ λ¬(λμ§κΈ°:throw)μ λ€λ₯Έ μ μ catch ꡬ문μ νμ catchκ° μ°μ¬μ§ μμλλ‘ (in the order of their appearance) ꡬλλλ€λ μ μ΄λ€. (μμ΄ κ΅¬λ¬Έμ μ°Έμ‘°νμκΈΈ) λ§μ΄ μ΄μνλ€. κ·Έλ₯ λ€μ μμ λ₯Ό 보μ
~cpp try{ ... } catch (logic_error& ex) { // μ¬κΈ°μμ λͺ¨λ logicμλ¬κ° μ‘νλ€. ... } catch (invalid_argument & ex){ // μ΄ λ¬Έμ μλμ νμ§ μλλ€. μμ catchꡬλΆμμ μ΄λ―Έ μ‘μ λ²λ¦°λ€. ... }
λ°λλ‘ κ°μν¨μλ₯Ό λΆλ₯Όλ μΌμ΄λλμΌμ΄ μλ€. λΉμ μ΄ κ°μν¨μλ₯Ό νΈμΆνλ©΄ ν¨μλ ν΄λΉ κ°μ²΄μ κ°μ₯ ν©λΉν ν¨μλ₯Ό dynamicμΌλ‘ μ°ΎμλΈλ€. μ΄κ²μ μ΅κ³ λ‘ μ ν©ν κ²(best fit)μ μλ―Ένμ§ κ°μ₯ μ²μμ μ°Ύμ μ§λ κ²(first fit)μ μλ―Ένλ κ²μ΄ μλλ€. μμ μμ€λ₯Ό λ°λλ‘ νλ€λ©΄
~cpp try{ ... } catch (invalid_argument & ex){ // invalid_argument μμΈλ μ΄κ³³μμ μ‘νλ€. ... } catch (logic_error& ex) { // μ¬κΈ°μ λͺ¨λ λ€λ₯Έ logic_error κ΄λ ¨μ μ΄κ³³μμ μ‘νλ€. ... }
μ΄λ κ² λμκ°λ κ±°λ€.
μμ μ 리
- μ²«μ§Έλ‘ μμΈ κ°μ²΄λ νμ λ³΅μ¬ λλ€.
- λμ§Έλ‘ λμ μ§λ κ°μ²΄λ ν¨μλ‘ μ λ¬λ λ λΉνμ¬ νμ λν λ³νμ΄ νμ μν₯ λ°κΈ° μ½λ€.
μμΈ κ°μ²΄λ μμμ κ·μΉμ λ°λ₯Έλ€. (μ€λͺ μ 보μκΈΈ)
- μ
μ§Έλ‘ μμ€ μ½λμ λνλλ μμλλ‘ μμΈλ μ‘νλ€.
1.5. Item 13: Catch exception by reference ¶
- Item 13: μμΈλ μ°Έμ‘°(reference)λ‘ μ‘μλΌ.
μ, λ¨Όμ pointer(by pointer)μ κ΄ν μ λ¬μ μκ°ν΄ 보μ. μ΄λ‘ μ μΌλ‘ μ΄ λ°©λ²μ throwμμΉμμ catchꡬλΆμΌλ‘ μμΈλ₯Ό νΉλ³ν λ³ν μμ΄ λλ¦° νλ‘κ·Έλ¨ μν μνμμ μ λ¬νκΈ°μ κ°μ₯ μ’μ λ°©λ²μ΄λ€. κ·Έ μ΄μ λ ν¬μΈν°μ μ λ¬μ ν΄λΉ μμΈ κ°μ²΄κ° 볡μ¬λλ μΌμμ΄ ν¬μΈν° κ°λ§ μ λ¬λλ λ°©λ²λ§μ μ·¨ν΄μΌ νκΈ° λλ¬Έμ΄λ€. λ§μ΄ μ’ μ΄μνλ° μμΈλ₯Ό 보면μ μ€λͺ
νλ€.
Item 12μμ μΈκΈνκ²κ³Ό κ°μ΄ μμΈλ 볡μ¬λμ΄μ μ λ¬λλ€. κ·Έκ±Έ μκ°ν΄λΌ.
~cpp class exception { ... }; void someFunction() { static exception ex; // μ΄λ κ² λ©λͺ¨λ¦¬μ νμ μ‘΄μ¬νλ κ°μ²΄λ§μ μ λ¬ν μ μλ€. ... throw &ex; // ν¬μΈν°λ‘ μ λ¬, ν΄λΉ ν¨μ μμμ λ²μ΄λλ―λ‘, staticλ§μ΄ μ΄μ λ¨μμ μλ€. ... } void doSomething() { try{ someFunction(); // μ¬κΈ°μμ exception *μ λμ§λ€. } catch ( exception *ex) { // exception* μ μ‘κ³ μλ¬΄λ° κ°μ²΄λ 볡μ¬λμ§ μλλ€. ... } }
μ΄ μ½λλ κΉ¨λνκ² λ³΄μ΄μ§λ§, μ΅μ μ±
μ μλλ€. μ΄λ° μΌμ μν΄μ νλ‘κ·Έλλ¨Έλ μμΈ κ°μ²΄λ₯Ό νμ νκ³ μλ νλ‘κ·Έλ¨μ μμ±ν΄μΌ ν κ²μ΄λ€. κ°λ¨ν μ μ(Global) staitcμΌλ‘ μ μΈνλ©΄ λλ€κ³ λ°λ¬Ένκ² μ§λ§, μ μμ μνμ±μ νλ‘κ·Έλλ¨Έκ° κ·Έκ±Έ μ½κ² κΉλ¨Ήμμ μλ€λλ° μλ€. λ€μ μμ λ₯Ό 보면
~cpp void someFunction() { exception ex; // local μμΈ κ°μ²΄μΈλ° μ΄ ν¨μμ μμμ λ²μ΄λλ©΄ νκ΄΄λμ΄ μ§λ€. ... throw &ex; // κ·ΈλΌ μ΄κ±΄ λ§μ§± νμΌμ΄λΌλ μ리 μ΄λ―Έ νκ΄΄λ κ°μ²΄λ₯Ό κ°λ¦¬ν€κ³ μμΌλ ... }μ μ΄κ±΄ λμ μ½λμ μ νμΌ κ²μ΄λ€. μ£Όμμμ μΈκΈνκ²κ³Ό κ°μ΄ ν¨μμμ λ²μ΄λλ©΄ newλ staticμ΄ μλμ΄μ λ§λ€μ΄μ§ κ°μ²΄λ νκ΄΄λμ΄ μ§λ€. κ·Έλ¦¬κ³ catchμμλ νκ΄΄λμ΄μ§ κ°μ²΄μ μ£Όμ κ°μ λ°κ² λλ κ²μ΄λ€.
ν΄λΉ μ½λλ₯Ό λ€μκ³Ό κ°μ΄ new heap objectλ‘ λ체ν μ μμ κ²μ΄λ€.
~cpp void someFunction() { ... throw new exception; // μ΄κ²λ μ΄νκ° μλκ², newμμ μμΈ λ°μνλ©΄ μ΄λ»κ² ν κ²κ°? ... }
μ΄κ²λ νΌν΄μΌ ν λ°©λ²μ΄λ€. μλνλ©΄ I-just-caught-a-pointer-to-a-destoyed-object λ¬Έμ λλ¬Έμ΄λ€. κ²λ€κ° catchꡬ문μμ μ§λ©΄ν λνλμ λ¬Έμ λ λ체 μ΄ ν¬μΈν°λ₯Ό λκ° μ΄λμ μ§μ°λλ μ΄λ€. λ€λ₯Έ λ©΄μΌλ‘ μκ°ν΄λ³Ό λ¬Έμ λ μμΈ κ°μ²΄κ° heapμμ λ°°μΉλλ€λ©΄ μ§μ μ§μ§ μμ μμΈ κ°μ²΄λ νμμμ΄ resource leakλ₯Ό λ°μ μν¬ κ²μ΄λ€. λ무 λ»ν μ΄μΌκΈ° μΈκ°. κ·Έλ¦¬κ³ νλ‘κ·Έλ¨μ νλ³΄κ° μ΄λ»κ² λ μ§ μμΈ‘ ν μλ μλ€. μκ·Έλ°κ°?
λͺλͺ ν΄λΌμ΄μΈνΈλ μ μ(global)μ΄λ μ μ κ°μ²΄λ₯Ό(static object)μ μ£Όμλ₯Ό λκΈ°μκ³ λ§νκ³ , λͺλͺμ heapμμ μμΈ κ°μ²΄μ μ£Όμλ₯Ό μ λ¬νμκ³ λ§νλ€. μ΄μ²λΌ ν¬μΈν°λ₯Ό ν΅ν μμΈμ μ λ¬μ (Catch by pointer) μ리μ‘ν λ¬Έμ λ₯Ό λ°μ μν¨λ€. μ§μ μ‘λκ°? μμ§μ μ‘λκ°? νμ λλ΅μ νμ€νμ§ μλ€.
κ²λ€κ° catch-by-pointer(ν¬μΈν°λ₯Ό ν΅ν μμΈ μ λ¬)μ μΈμ΄μμμ μ¬λλ€μ λ립μ μ λ νλ€. λ€κ°μ§μ νμ€ μμΈ κ°μ²΄λ€λ€( bad_alloc(Item 8:operator newμμ λΆμΆ©λΆν λ©λͺ¨λ¦¬ λ°ν), bad_cast(Item 2:dynamic_castμμ μ°Έμ‘° μ€ν¨), bad_typeid(dynamic_castμΌλ nullν¬μΈν°λ‘ λ³ν), bad_exception(Item 14:μμΈ‘ λͺ»νλ μμΈλ‘ λΉ μ§λ κ² unexpected exception λ¬Έμ ) κ° μμΈ κ°μ²΄λ€μ λͺ¨λ κ²μΈλ°, μ΄λ€μ ν₯ν κΈ°λ³Έμ μΈ ν¬μΈν°λ μ‘΄μ¬νμ§ μλλ€. κ·Έλμ λΉμ μ μμΈλ₯Ό κ°μΌλ‘(by value)νΉμ μ°Έμ‘°λ‘(by reference) λ°μλ λμμ΄ μλ€.
Catch-by-valueλ νμ€ μμΈ κ°μ²΄λ€ μμμμ μμΈ κ°μ²΄μ μμ λ¬Έμ μ κ΄ν΄μ κ³ λ―Όν νμκ° μλ€. νμ§λ§ μμΈκ° μ λ¬λ λ λλ²μ 볡μ¬κ° μ΄λ£¨μ΄ μ§λ€λκ² λ¬Έμ λ€. (Item 12μ°Έκ³ ) κ²λ€κ° κ°μΌλ‘μ μ λ¬μ slicing problemμ΄λΌλ λ¬Έμ λ₯Ό λ°μμν¨λ€. μ΄κ² λλ νλ©΄, λ§μ½ νμ€ μμΈ κ°μ²΄μμ μ λ(μμ)ν΄μ λ§λ€μ΄μ§ μμΈ κ°μ²΄λ€μ΄ ν΄λΉ κ°μ²΄μ λΆλͺ¨λ‘ λμ μ§λ€λ©΄, λΆλͺ¨ ννΈ λΆλΆλ§ κ°μΌλ‘ λλ²μ§Έ 볡μ¬μμ 볡μ¬λμ΄μ μ λ¬λμ΄ λ²λ¦°λ€λ λ¬Έμ λ€. μ¦ μλΌλ²λ¦¬λ λ¬Έμ "slice off" λΌλ ννμ΄ λ€μ΄ κ°λ§ νκ² μ§. κ·Έλ€μ data memberλ μλ§ λΆμ‘±ν¨μ΄ μ겨 λ²λ¦΄ κ²μ΄κ³ ν΄λΉ κ°μ²΄μμμ κ°μ ν¨μλ₯Ό λΆλ₯Όλ μμ λ¬Έμ κ° λ°μν΄ λ²λ¦΄ κ²μ΄λ€. μλ§ λ¬΄μ‘°κ±΄ λΆλͺ¨ κ°μ²΄μ κ°μ ν¨μλ₯Ό λΆλ₯΄κ² λ κ²μ΄λ€.(μ΄ κ°μ λ¬Έμ λ ν¨μμ κ°μ²΄λ₯Ό κ°μΌλ‘ λκΈΈλλ λκ°μ΄ μ κΈ° λλ€.) μλ₯Ό λ€μ΄μ λ€μμ μκ°ν΄ 보μ
~cpp class exception { public: virtual const char * what() throw(); ... } class runtime_error:public exception{ ... }; class Validation_error : public runtime_error{ // μ ν΄λΉ κ°μ²΄λ runtime_errorλ₯Ό μμν΄μ λ§λ€μκ³ public: virtual const char * what() throw(); // μ΄ κ°μν¨μλ exceptionμμ μλ κ²μ΄λ€. ... } void someFunction() { ... if ( a validation ν μ€νΈ μ€ν¨){ throw Validation_error(); } ... } void doSomething() { try{ someFunction(); } catch (exception ex) { // item 12μμ μΈκΈνλ― exceptionμ μμ μμΈκ°μ²΄λ€μ λ€ μ‘νλ€. cerr << ex.what(); // κ°μΌλ‘ λΆλͺ¨λ§ 볡μ¬νκΈ° λλ¬Έμ what() κ°μν¨μλ exceptionμμ // κ°μ ν¨μκ° λΆλ¦°λ€. κ°λ°μμ μλλ Validation_error μμ κ°μν¨μλ₯Ό // λΆλ₯΄κΈΈ μνλ κ² μ΄μλ€. ... } }μ£Όμμ μΈκΈλμ΄ μλ―μ΄ μ΄ λ²μ μ slicing λ¬Έμ κ° λ°μνλ€. ꡬ차ν μ€λͺ κ·μ°λ€. κ²°λ‘ μ κ°μΌλ‘(by value)μ μμΈ κ°μ²΄ μ λ¬μ μ΄λ° slicing λ¬Έμ λ‘ λΉμ μ΄ μνλ νλμ μ λλ‘ λͺ»νλ€.
μμ κ·ΈλΌ λ¨μ건 μ€μ§ catch-by-reference(μ°Έμ‘°λ‘μ μμΈ μ λ¬)μ΄λ€. catch-by-referenceλ μ΄μ κΉμ§μ λ
Όμλ₯Ό κΉ¨λμ΄ μμ μ€λ€. catch-by-pointerμ κ°μ²΄ μμ λ¬Έμ μ νμ€ μμΈ νμ
λ€μ μ‘λκ±°μ λν μ΄λ €μ, catch-by-valueμ κ°μ slicing λ¬Έμ λ λλ² λ³΅μ λλ μ΄λ €μμ΄ μλ€. μ°Έμ‘°λ‘μ μμΈ μ λ¬μμ μμΈ κ°μ²΄λ μ€μ§ νλ² λ³΅μ¬λμ΄ μ§ λΏμ΄λ€.
λ€μ μμ λ₯Ό 보μ.
~cpp void someFunction() { ... if ( validation ν μ€νΈ μλ¬ ){ throw Validataion_error(); } ... } void doSomething() { try{ someFunction(); } catch (exception& ex){ // μ΄λΆλΆμ μ°Έμ‘°λ‘λ§ λ°κΎΈμλ€. μ΄μ μ μμ μ νΉλ³ν λ°λκ² μλ€. // νμ§λ§ μ΄λΆλΆμ΄ λ°λμ΄μ cerr << ex.what(); // μ¬κΈ°μμ κ°μ ν¨μλ Validation_errorμ λ©μλκ° λΆλ¦°λ€. ... } }
ν΄λΉ μμ€λ catchμμ μ°Έμ‘°λ‘λ§μ΄ λ°λμλ€. &νλλ§μ΄ μΆκ°λμ΄ μ§κΈκΉμ§ μ κΈ°λ λ¬Έμ κ° μ¬λΌμ Έ λ²λ¦°λ€.
catch-by-referenceλ μ΄μ κΉμ§μ λ¬Έμ μ λͺ¨λ ν΄κ²°μ±
μ μ μνλ€. (slicing, deleteλ¬Έμ etc)κ·ΈλΌ μ΄μ κ²°λ‘ μ νλ μλκΉ?
Catch exception by reference!
1.6. Item 14: Use exception specifications judiciously. ¶
- Item 14: μμΈλ₯Ό μ μ€νκ² μ¬μ©νλΌ.
μΌλ¨ μ΄ μ£Όμ λ₯Ό λΆμ νλ μ΄λ μμΌλ¦¬λΌ.:μμΈλ μ μ ν κ³³μ ννλμ΄μΌ νλ€. κ·Έλ€μ μ½λλ₯Ό λ μ΄ν΄κ°κΈ° νΈνκ² λ§λ€μ΄ μ€λ€. μλνλ©΄ μλ§ λͺ
μμ μΌλ‘ ννλ μμΈ μνκ° μ λ¬(λμ :throw-μ΄ν λμ§λ€λ ννμΌλ‘) λ κ²μ΄κΈ° λλ¬Έμ΄λ€. κ·Έλ μ§λ§ μμΈλ μ£Όμ(comment)보λ€λ λͺ¨νΈνλ€. μ»΄νμΌλ¬λ λλλ‘ μ»΄νμΌμ€μ μ νν μΌμΉνμ§ μμ μμΈλ€μ λ°κ²¬ν μλ μμΌλ©°, λ§μ½ ν¨μκ° μμΈ μ€ν(λͺ
μΈ:μ΄νλͺ
μΈ)μμ μ λλ‘ λͺ
κΈ°λμ§ μμ μμΈλ₯Ό μ λ¬(λμ‘)λ€λ©΄ μλͺ»μ μ€νμκ°(runtime)μ λ°κ²¬λλ€. κ·Έλ¦¬κ³ νΉλ³ν ν¨μμΈ unexpectedλ μλμΌλ‘ λΆλ¦¬κ² λλ€. μ΄λ λ μμΈμ²λ¦¬λ μλΉν λ§€λ ₯μ μΈ λ©΄μ κ°μ§κ³ μλ€.
- νμ§λ§ λ³΄ν΅ μλ¦λ€μμ νλ©΄μ΄ μλ λ΄λ©΄μ μ‘΄μ¬νλ€.
λ€μμ f1ν¨μμ κ°μ΄ μλ¬΄λ° μμΈλ₯Ό λ°μ μμν€λ ν¨μμ κ΄ν΄μ μκ°ν΄ 보μ. μ λ° ν¨μλ μλ§ μ΄λ ν μμΈλΌλ λ°μμν¬μ μμ κ²μ΄λ€.
~cpp extern void f1();μ κ·ΈλΌ μμΈ λͺ μΈμ΄ μ μ©λ f2λ₯Ό 보μ. λ€μμ μ€μ§ intλ§μ μμΈλ‘ λμ§κ²μ΄λ€.
~cpp void f2() throw(int);f1μ΄ f2μ ν¨μ λͺ μΈκ³Ό λ€λ₯Έ μμΈλ₯Ό λμ§λλΌλ, C++μμμλ f2μμ f1λ₯Ό λΆλ₯΄λκ²μ νμ©νλ€.
~cpp void f2() throw(int) { ... f1(); ... }μ΄λ° μ μ°ν κ²½μ°λ λ§μ½ μμΈ λͺ μΈμ κ΄ν μλ‘μ΄ μ½λκ° κ³Όκ±°μ μμΈ λͺ μΈκ° λΆμ‘±ν μ½λμ μ κ²°ν©ν μ μμμ 보μΈλ€.
λΉμ μ μ»΄νμΌλ¬κ° μμΈ μ²λ¦¬κ·μ μ λ§μ‘±νμ§ μμ 루ν΄μ κ°μ§ ν¨μμ μ½λλ₯Ό νΈμΆνλλ° λ³ λ¬΄λ¦¬μλ€κ³ , κ·Έλ¬ν νΈμΆμ΄ μλ§ λΉμ μ νλ‘κ·Έλ¨μμ νλ‘κ·Έλ¨μ μ€μ§λ₯Ό μ λνκΈ° λλ¬Έμ λΉμ μ μννΈμ¨μ΄λ₯Ό λ§λ€λ μ΅λν κ·Έλ° λ§μ‘±λμ§ μμ νΈμΆμ μ΅μν νλλ‘ κ²°κ³Όλ₯Ό μ λν΄μΌ ν κ²μ΄λ€. μμμ κ°μ₯ μ’μ λ°©ν₯μ ν
νλ¦Ώμμμμ μμΈ μ€νλ₯Ό μ΅λν νΌνλ κ²μ΄λ€. μ λ€μμ μ΄λ ν μμΈλ λμ§μ§ μμ ν
νλ¦Ώμ μκ°ν΄ 보μ.
~cpp template<class T> bool operator==(const T& lhs, const T& rhs) throw() { return &lhs == &rhs; }μ΄ ν νλ¦Ώμ oprator== ν¨μλ₯Ό λͺ¨λ νμ μ μ©μν€λ κ²μ΄λ€. μλ§ κ°μ μ£Όμμ κ°μ νμ μ΄λ©΄ trueλ₯Ό λ°ννμ§λ§ μλλΌλ©΄ κ·Έκ²μ falseλ₯Ό λ°ννλ€. μ΄λ° ν νλ¦Ώμ μλ¬΄λ° μμΈλ λμ§μ§ μμ ν νλ¦ΏμΌλ‘ λΆν° ν¨μκ° λ§λ€μ΄μ§λ μνμ λ°λΌ μ ν©ν μμΈκ° ν¬ν¨λλ€. νμ§λ§ κ·Έκ²μ κΌ μ¬μ€μ΄ μλλ€. μλνλ©΄ operator&(μ£Όμ λ°ν operator)κ°κ° κΌ κ°μ λͺλͺμ νλ€μ μν΄μ overloadλμκΈ° λλ¬Έμ΄λ€. λ§μ½ μ¬μ€μ΄ κ·Έλ¬νλ€λ©΄ operaotr&κ° operator== μμͺ½μμ λΆλ¦΄λ μμΈλ₯Ό λμ§ κ²μ΄λ€. κ·Έλ κ² λλ©΄ μ°λ¦¬μ μμΈ λͺ μΈλ κ±°λΆλκ³ , κ³§μ₯ unexpected λ‘ μ§μ§νκ² λλκ±°λ€.
μ΄λ¬ν νΉλ³λ μμ λ λ μΌλ°μ μΈ λ¬Έμ λ‘, λ€μ λ§νμλ©΄ ν
νλ¦Ώμ ν μΈμλ‘ μ λ¬λλ μμΈμ κ΄ν μ 보λ₯Ό μμλΌ κΈΈμ΄ μλ€λ μ λ νλͺ«μ΄λ€. μ°λ¦¬λ κ±°μ ν
νλ¦Ώμ μν μλ―Έμλ μμΈ λͺ
μΈλ₯Ό μ 곡ν μ μλ€λ μ΄μΌκΈ°λ€. μλνλ©΄ ν
νλ¦Ώμ κ±°μ λ³ν¨μμ΄ κ·Έλ€μ΄ ν μΈμλ₯Ό λͺκ°μ§μ λ°©μμΌλ‘λ§ μ°κΈ° λλ¬Έμ΄λ€. κ²°λ‘ μ? ν
νλ¦Ώκ³Ό μμΈλ μ΄μΈλ¦¬μ§ μλλ€.!
- λλ²μ§Έλ‘ λΉμ μ unexpectedνΈμΆμ λ§κΈ°μνμ¬ λΆμ‘±ν μμΈ λͺ
μΈμ κ·μ μΌλ‘ μΈνμ¬ λΆλ¦¬λ ν¨μμμμ μμΈ λͺ
μΈλ₯Ό μλ΅ν μ μλ€.
~cpp typedef void (*CallBackPtr) (int eventXLocation, int event YLocation, void *dataToPassBack); class CallBack{ public: CallBack(CallBackPtr fPtr, void *dataToPassBack) :func(fPtr), data(dataToPassBack){} void makeCallBack(int eventXLocation, int eventYLocation) const throw(); private: CallBackPtr func; void *data } void CallBack::makeCallBack(int eventXLocation, int eventYLocation) { func(eventXLocation, eventYLocation); }μ΄ μ½λμμ makeCallBackμμ funcμ νΈμΆνλκ²μ funcμ΄ λμ§λ μμΈμ κ²μ μκΈΈμ΄ μμ΄μ μμΈ λͺ μΈμ μλ°νλ μνν μν©μΌλ‘ κ°μ μλ€.
μ΄λ° λ¬Έμ λ λ€μκ³Ό κ°μ΄ CallBackPtrμμ μμΈ λͺ
μΈλ₯Ό μ’λ ꡬ체ν μμΌμ μ κ±°ν μ μλ€.
~cpp typedef void (*CallBackPtr) (int eventXLocation, int event YLocation, void *dataToPassBack) throw();λ€μκ³Ό κ°μ΄ νμ΄ μ μΈλμμΌλ©΄ callbackν¨μ λ±λ‘μ μ무κ²λ λμ§μ§ μλλ€λ 쑰건μ΄λΌλ©΄ μμΈλ₯Ό λ°μν κ²μ΄λ€.
~cpp // μμΈ λͺ μΈκ° μλ ν¨μ void callBackFcn1(int eventXLocation, int event YLocation, void *dataToPassBack); void *vallBackData; ... CallBack c1(callBackFcn1, callBackData); // μλ¬λ€ callBackFcn1μ μ¬κΈ°μμ νμ΄ λ§μ§ μμ. μλ¬λ₯Ό λμ§κ²μ΄λ€. // μμΈ λͺ μΈκ° μλ ν¨μ void callBackFcn2(int eventXLocation, int event YLocation, void *dataToPassBack); throw() CallBack c1(callBackFcn2, callBackData); // 보λ€μνΌ μλ§λ νμ΄λ€.
μ΄λ¬ν ν¨μ ν¬μΈν° μ λ¬μ κ΄λ ¨μ μ΅κ·Όμ μΆκ°λκ±°λ λ§μ½ μ»΄νμΌλ¬κ° μ§μ λͺ»νλ€κ³ ν΄λ λλκ²μ μλ€. (μ΄μ±
μ 1996λ
μ λμλ€. νμ§λ§ μ§κΈλ(2001λ
μ λ) μ λλ‘ μ§μνλ μ»΄νμΌλ¬κ° λ§μ§ μμκ±Έλ‘ μλ€.) λ§μ½ μ»΄νμΌλ¬κ° μ²λ¦¬ λͺ»νλ€λ©΄ μ΄λ° μ€μμ λ°©μ§λ λΉμ μμ μκ² λ¬λ Έλ€.
- μΈλ²μ§Έλ‘ λΉμ μ "the system"μ΄ μλ§ λμ§λ μμΈλ₯Ό νΈλ€λ§ν΄μ unexceptedμ νΈμΆμ νΌν μ μλ€. μ΄λ¬ν μμΈλ λ§μ λΆλΆμ΄ newμ new[]μ λ©λͺ¨λ¦¬ ν λΉ μμΈμμ bad_allocμ΄ λ°μνμ¬ λ°μνλ€. λ§μ½ λΉμ μ΄ newλ₯Ό μ΄λ€ ν¨μμμ μ΄λ€λ©΄ μ°μ°μ΄λΌλ bad_alloc μμΈλ₯Ό λ§λ μ μλ κ°λ₯μ±μ λ΄ν¬νλ μ
μ΄λ€.
λ§μ½ unexpectedμμΈλ₯Ό λ§λκ²μ΄ μ€μ©μ μ΄μ§ λͺ»νλ€λ©΄ λΉμ μ C++κ° unexpectedλ₯Ό λ€λ₯Έ νμμΌλ‘ λ°κΎΈμ΄ λ²λ¦¬λ κΈ°λ₯μ μ΄μ©ν΄μ κ·Έλ¬ν λΉμ€μ©μ μΈ μνλ₯Ό λ§νν μ μλ€. λ€μ μλ unexpectμ κ°μ μμΈλ₯Ό UnexpectedException κ°μ²΄λ‘ λ°κΎΌκ²μ μκ°ν΄ λ³Έλ€.
~cpp class UnexpectedException {}; void convertUnexpected() { throw UnexpectedException(); }
κ·Έλ¦¬κ³ unexpected ν¨μλ₯Ό convertUnexpectedλ‘ κ΅μ²΄νλ€.
~cpp set_unexpected(convertUnexpected);μ΄λ κ² νλ©΄ unexpectedμμΈλ convertUnexpectedλ₯Ό νΈμΆνλ€. μ¦, μλ‘μ΄ UnexpectedException κ°μ²΄λ‘ μμΈκ° κ΅μ²΄λμλ€. νμ§λ§ μ 곡λλ μμΈ λͺ μΈμμ unexpectedλ₯Ό λ°©μ§ν λ €λ©΄ UnexpectedException μμΈλ₯Ό ν¬ν¨ν΄μΌ νλ€. μμΈλ₯Ό κ°μ²΄λ‘ λμ‘κΈ°μ.. (λ§μ½ μμΈ λͺ μΈμ UnexpectedExceptionμ λ£μ§ μμλ€λ©΄ unexpectedκ° κ΅μ²΄λμ§ μμ κ²μ²λΌ terminateκ° λΆλ¦΄κ²μ΄λ€.)
λ λ€λ₯Έ λ°©λ²μ unexpected μμΈλ₯Ό κ·Έλ₯ unexpectedμ μν μ νμ¬μ μμΈλ₯Ό κ³μ λμ§κΈ°(rethrow)ννλ‘ λ°κΎΈμ΄ λ²λ¦¬λ κ²μ΄λ€. μ΄λ κ² κ΅μ²΄νλ©΄ μμΈλ μλ§ μλ‘μ΄ νμ€μ bad_exception μ λμ§λ ννλ‘ λ°λλ€. (μ κ· C++λΌμ΄λΈλ¬λ¦¬μ ν¬ν¨)
~cpp void convertUnexpected() { throw() // μ΄κ±΄ νμ μ μμΈλ₯Ό κ³μ λμ§λ€λ μλ―Έ } set_unexpected(convertUnexpected);λ§μ½ μμ κ°μ΄ νκ³ bad_exception(νμ€ λΌμ΄λΈλ¬λ¦¬ μμ exceptionμ κΈ°λ³Έ μμΈ ν΄λμ€)λ₯Ό λΉμ μ λͺ¨λ μμΈ λͺ μΈμ ν¬ν¨μν€λ©΄ λΉμ μ κ²°μ½ λΉμ γ΄μ νλ‘κ·Έλ¨μ΄ λΆμμ λ©μΆμ΄ λ²λ¦¬λκ²μ λν κ±±μ μ ν μλ μμ κ²μ΄λ€. κ±°κΈ°λ€κ° κ·μ μ λ§μ§μλ μμΈλ€λ bad_exceptionμΌλ‘ κ΅μ²΄λκ³ μμΈλ κΈ°λ³Έ μμΈ λμ μ λ€μ λμ νΌμ§λ€.(propagate)
--
μ΄μ λΉμ μ μμΈ λͺ μΈκ° λ§μ λ¬Έμ λ₯Ό κ°μ§κ³ μμμ μμμ μ΄ν΄ ν κ²μ΄λ€. μ»΄νμΌλ¬λ κ·Έλ€μ λΆλΆμ μΈ μ°μμλ₯Ό κ²μ¬ν΄μ ν νλ¦Ώμμ λ¬Έμ λ₯Ό λ°μν μμ§λ₯Ό μμΌλ©°, μ»΄νμΌλ¬λ μμΈλ‘ κ·μΉμλ°μ νκΈ° μ½κ³ , μ»΄νμΌλ¬κ° μ λλ‘ λμ§ μμΌλ©΄ νλ‘κ·Έλ¨μ λΆμμ λ©μΆμ΄ μ§λλ‘ μ λν κ²μ΄λ€. μμΈ λͺ μΈ μμ λλ€λ₯Έ λ¬Έμ λ₯Ό μκ³ μλλ°, μμΈλͺ μΈλ λμ μμ€μ νΈμΆμκ° μμΈ λ°μμ λλΉν λλ unexpectedλ‘μ κ²°κ³Όλ¬Όμ λ§λ€μ΄ λΈλ€.
μ΄μ λΉμ μ μμΈ λͺ μΈκ° λ§μ λ¬Έμ λ₯Ό κ°μ§κ³ μμμ μμμ μ΄ν΄ ν κ²μ΄λ€. μ»΄νμΌλ¬λ κ·Έλ€μ λΆλΆμ μΈ μ°μμλ₯Ό κ²μ¬ν΄μ ν νλ¦Ώμμ λ¬Έμ λ₯Ό λ°μν μμ§λ₯Ό μμΌλ©°, μ»΄νμΌλ¬λ μμΈλ‘ κ·μΉμλ°μ νκΈ° μ½κ³ , μ»΄νμΌλ¬κ° μ λλ‘ λμ§ μμΌλ©΄ νλ‘κ·Έλ¨μ λΆμμ λ©μΆμ΄ μ§λλ‘ μ λν κ²μ΄λ€. μμΈ λͺ μΈ μμ λλ€λ₯Έ λ¬Έμ λ₯Ό μκ³ μλλ°, μμΈλͺ μΈλ λμ μμ€μ νΈμΆμκ° μμΈ λ°μμ λλΉν λλ unexpectedλ‘μ κ²°κ³Όλ¬Όμ λ§λ€μ΄ λΈλ€.
μ΄μΌκΈ°λ₯Ό μν΄ Item 11μ μμ λ₯Ό κ·Έλλ‘ λ³΄μ
~cpp class Session{ public: ~Session(); ... private: static void logDestuction(Session *objAddr) throw(); }; Session::~Session() { try{ logDestruction(this); } catch ( ... ) {} }Sessionμ νκ΄΄μλ logDestructionμ νΈμΆνλ€. νμ§λ§ λͺ μμμ μ΄λ ν μμΈλ ν΄λΉ logDestructionμμ λμ§μ§ λͺ»νλλ‘ λ§μλμλ€. νλ² logDestuctionμ΄ μ€ν¨ν λ λΆλ¦¬λ ν¨μλ€μ λνμ¬ μκ°ν΄ 보μ. μ΄κ²μ μλ§ μΌμ΄λμ§ μμ κ²μ΄λ€. μ°λ¦¬κ° μκ°νλλ‘μ΄κ±΄ μλΉν μμΈ λͺ μΈμ κ·μ μλ°μΌλ‘ μΈλνλ μ½λμ΄λ€. μ΄λ° μμΈ‘ν μ μλ μμΈκ° logDestructionμΌλ‘ λΆν° νΌμ§λ unexpectedκ° ν릴 κ²μ΄λ€. κΈ°λ³Έμ μΌλ‘ κ·Έκ²μ νλ‘κ·Έλ¨μ λ©μΆλ€. μ΄ μμ λ κ·Έκ²μ μμ λ²μ μ΄μ§λ§, κ·Έλ° μνμ Session νκ΄΄μμ μ μμκ° μν κΉ? μμ±μλ λͺ¨λ κ°λ₯ν μμΈ λ₯Ό μ‘μΌλ €κ³ λ Έλ ₯νλ€. κ·Έλμ 그건 Session νκ΄΄μμ catchλΈλμμμνλλ κ²μ΄ λ€λ€λ©΄ 그건 λΆκ³΅νν μ²μ¬λΌκ³ 보μΈλ€. λ§μ½ logDestructionμ΄ μλ¬΄λ° μμΈ λͺ μΈλ₯Ό νμ§ μλλ€λ©΄, I'm-willing-to-catch-it-if-you'll-just-give-me-a-chance μλ리μ€λ κ²°μ½ μΌμ΄λμ§ μμκ²μ΄λ€. (μ΄λ° λ¬Έμ μ μλ°©μΌλ‘ unexpectedμ κ΅μ²΄μ λν μ€λͺ μ μν΄ μΈκΈν΄ λμλ€.)
μμΈ λͺ
μΈμ κ· νμλ μκ°μ μ€μνκ²μ΄λ€. κ·Έκ²μ μμΈ λ°μμ μμνλ ν¨μλ€μ μμΈ μ’
λ₯λ€μ 보면 νλ₯ν λ¬Έμνκ° λ κ²μ΄κ³ , μλͺ»λ μμΈ λͺ
μΈμ μν©νμ νλ‘κ·Έλ¨μ κΈ°λ³Έμ μΌλ‘ μ£Όμ΄μ§λ μν μ¦, μ¦μ λ©μΆλ κ²μ μ λΉνν λ§νΌ μλͺ»λ μΌμ΄λ€. κ°μ μκ°μΌλ‘ μμΈλ μ»΄νμΌλ¬μ μνμ¬ μ€μ§ λΆλΆμ μΈ μ κ²λ§μ λΉνκ³ μμΈλ μλνμ§ μμ μλͺ»μ μμ°νκΈ° μ¬μΈκ²μ΄λ€. κ²λ€κ° μμΈλ unexpected μμΈμμ λ°μνλ λμ λ 벨μ μμΈ μ‘λ λ¬Έμ μ λνμ¬ μλ°©ν μ μλ€.
μ μ΄λ°κ²λ€μ΄ μμΈ λͺ
μΈλ₯Ό νλͺ
νκ² μ¬μ©νλλ° μΌμ‘°ν κ²μ΄λ€. λΉμ μ ν¨μμ μμΈλ₯Ό λνκΈ° μ μ μ΄λ° μ¬νμ λνμ¬ νλ²μ―€ μκ°ν΄ 보μ.
1.7. Item 15: Understand the costs of exception handling ¶
- Item 15: μμΈ νΈλ€λ§μ λν λΉμ© μ§λΆ λν μ΄ν΄
μ κ·ΈλΌ μ ν μμΈ νΈλ€λ§μ νμ§ μμμλμ μ§λΆ λΉμ©μ μκ°ν΄ 보μ, λΉμ μ κ°μ²΄λ€μ΄ μ μ¬λκ³ , μ μ§λλ νΈλμ΄ νμν λ°μ΄ν° ꡬ쑰μ μ¬μ©μ μν΄ κ³΅κ°μ λν λΉμ© μ§λΆμ νλ€. κ·Έλ¦¬κ³ λΉμ μ μ΄λ° λ°μ΄ν° ꡬ쑰λ€μ κ°±μ νκ³ μ μ§νλλ° νμν μκ°μ λν λΉμ©μ μ§λΆνλ€. μ΄λ° λΉμ©λ€μ μΌλ°μ μΌλ‘ μ λΉν μꡬμ΄λ€. λ°λ©΄μ νλ‘κ·Έλ¨μ΄ μμΈλ₯Ό μν μ§μμ΄ μμ΄ μ»΄νμΌ λλ€λ©΄ μμΈ μ§μμ νκ³ μ»΄νμΌ νλ λ°λμ κ²½μ°λ³΄λ€ μ’λ λΉ λ₯΄κ³ , μ’λ μμ μ©λμ μ°¨μ§νλ€.
μ΄λ‘ μ μΌλ‘ λΉμ μ μ΄λ°(μμΈ) λΉμ©μ μ§μΆ(μ ν,select)μ΄ μμ΄μΌ νλ€.:C++μ ν λΆλΆμΈ μμΈ, μ»΄νμΌλ¬λ μμΈλ₯Ό μ§μν΄μΌνλ€.
νλ‘κ·Έλ¨μ μΌλ°μ μΌλ‘ λ
립μ μΌλ‘ object νμΌλ€μ΄ μμ±λμ΄ μ§κ³ , λ¨μ§ νλμ μμ±λμ΄ λ§λ€μ΄μ§ objectνμΌμμ μμΈ μ²λ¦¬κ° μλ€λ©΄ λ€λ₯Έ κ²λ€μμ μμΈ μ²λ¦¬κ° μλ¬΄λ° μλ―Έκ° μκΈ°λλ¬Έμ, λΉμ μ΄ μμΈμ²λ¦¬μ½λλ₯Ό μ¬μ©νμ§ μλλ€λ©΄, λΉμ μ μ»΄νμΌλ¬ μ μμ¬λ€μ΄ μ΄λ° μμΈλ€μ μ§μμ μΌμ΄λλ λΉμ©μ μμ¨ κ²μ΄λΌκ³ μμνλ€. κ²λ€κ° objectνμΌμ΄ μμΈλ₯Ό λΉΌκΈ°μν΄ μλ¬΄λ° μνΈκ°μ λ§ν¬κ° λμ§ μλλ€λ©΄ μμΈ μ²λ¦¬κ° λ€μ΄κ° λΌμ΄λΈλ¬λ¦¬μμ λ§ν¬λ μ΄λ¨κΉ? μ¦, νλ‘κ·Έλ¨μ μ΄λ€ λΆλΆμ΄λΌλ μμΈλ₯Ό μ¬μ©νλ€λ©΄ λλ¨Έμ§ νλ‘κ·Έλ¨μ λΆλΆλ€λ μμΈλ₯Ό μ§μν΄μΌ νλ€. μ΄λ° λΆλΆμ μμΈ μ²λ¦¬ μν©μ μ€νμκ°μ μ νν μμΈλ₯Ό μ‘λ μνμ΄ λΆκ°λ₯ νκ² λ§λ€κ²μ΄λ€.
λ¬Όλ‘ μ κ²μ μ΄λ‘ μ΄λ€. μ€μ§μ μΌλ‘ μμΈ μ§μ λ°΄λλ€μ λΉμ μ΄ μμΈ μμ±μ μν μ½λμ 첨κ°λ₯Ό λΉμ μ΄ μμΈλ₯Ό μ§μνλλ λ§λλμ λ°λΌ μ‘°μ ν μ μλλ‘ λ§λ€μ΄ λμλ€.(μμ±μμ£Ό:μ¦ μμΈ κ΄λ ¨ μ²λ¦¬μ on, offκ° κ°λ₯νλ€.) λ§μ½ λΉμ μ΄ λΉμ μ νλ‘κ·Έλ¨μ μ΄λ ν μμκ³Ό, μ°κ³λλ λͺ¨λ λΌμ΄λΈλ¬λ¦¬μμ try, throw, catchλ₯Ό λΉΌκ³ μμΈ μ§μ μ¬νμ λΉΌκ³ λΉμ μ€μ€λ‘ μλ, ν¬κΈ° κ°μ μμΈμ²λ¦¬μ λ°μνλ λ¨μ μ μ κ±°ν μ μμ κ²μ΄λ€. μκ°μ΄ μ§λ κ°μ λ°λΌ λΌμ΄λΈλ¬λ¦¬μ μ°¨μ©λλ μμΈμ μ²λ¦¬λ μ μ λμ΄λκ² λκ³ , μμΈλ₯Ό μ κ±°νλ νλ‘κ·Έλλ°μ κ°μλ‘ λ΄κ΅¬μ±μ΄ μ½ν΄ μ§κ²μ΄λ€. νμ§λ§, μμΈμ²λ¦¬λ₯Ό λ°°μ ν μ»΄νμΌμ μ§μνλ νμ¬μ C++ μννΈμ¨μ΄ κ°λ°μμ μνλ νμ€ν μμΈμ²λ¦¬ λ³΄λ€ μ±λ₯μμ μ°μλ₯Ό μ νλ€. κ·Έλ¦¬κ³ κ·Έκ²μ λν μμΈ μ λ¬(propagate) μ²λ¦¬μ, μμΈλ₯Ό μκ°νμ§ μμ λΌμ΄λΈλ¬λ¦¬λ€μ μ¬μ©μ 무리μλ μ νμ΄ λ κ²μ΄λ€.
λλ²μ§Έλ‘ try λΈλ‘μΌλ‘λΆν°μ μμΈλ₯Ό μ‘λ(exception-handling)μ λν λΉμ©μ μκ°ν΄ 보μ μ΄κ²μ λΉμ μ΄ catchλ‘ μμΈ νλλ₯Ό μ‘κΈ°λ₯Ό μν λ λ§λ€ μꡬλλ λΉμ©μ΄λ€. κ°κΈ° λ€λ₯Έ μ»΄νμΌλ¬λ€μ μλ‘ λ€λ₯Έ λ°©μμΌλ‘ tryλΈλ‘μ μ μ©μ νλ€. κ·Έλμ ν΄λΉ λΉμ©μ κ° μ»΄νμΌλ¬λ§λ€ λ€λ₯΄λ€. κ·Έλ₯ λμΆ© μ΄λ¦Όμ‘μμ μμνλ©΄, λ§μ½ tryλΈλ‘μ μ°κ²λλ©΄, λΉμ μ μ 체μ μΈ μ½λ μ¬μ΄μ¦λ 5-10%κ° λμ΄λκ³ , λΉμ μ μ€ν μκ° μμ λΉμ·ν μμ€μΌλ‘ λμ΄λλ€. μ΄μ μλ¬΄λ° μμΈλ₯Ό λμ§μ§ μλλ€κ³ μκ°νμ;μ°λ¦¬κ° μ¬κΈ°μμ ν λ‘ νκ³ μλκ²μ λ¨μ§ λΉμ μ νλ‘κ·Έλ¨λ΄μμ tryκ° κ°μ§λ λΉμ©λ§μ΄ μλλ€. μ΄λ° λΉμ©μ μ΅μνλ₯Ό μν΄μ μλ§ λΉμ μ νμνμ§ μλ tryλΈλμ νΌν΄μΌλ§ ν κ²μ΄λ€.
μ»΄νμΌλ¬λ μλ§£μ try λΈλμ μμΈ μ€νμ λν μ½λλ₯Ό μνμ¬ μ½λλ₯Ό λ§λ€μ΄λ΄μΌ νλ€. κ·Έλμ μ½λ μ€ν©μ μΌλ°μ μΌλ‘ νλμ tryλΈλλΉ κ°μ μμ λΉμ©μ μ§μΆνκ² λλ€. μ κΉ?(excuse me?) λΉμ μ μμΈ μ€ν©μ΄ λ¨μ μ€ν©μΈ, μ¦ μ½λλ₯Ό λ§λ€μ΄ λ΄λκ±Έ μκ°νμ§ μλλ€κ³ λ§νλ€. μ, λΉμμ κ·Έλ° μκ°μ κ΄ν΄μ μ‘°κΈ μλ‘μ΄ λͺκ°μ§λ₯Ό κ°μν΄ λ΄γ
.
λ¬Έμ μ μ΄μ μ μμΈκ° λμ§λ λΉμ©μ΄λ€. μ¬μ€ μμΈλ ν¬κ·ν κ²μ΄λΌ 보기 λλ¬Έμ κ·Έλ κ² ν¬κ² κ°μν λ΄μ©μ΄ μλλ€. κ·Έλ€μ΄ μμΈμ μΈ(exceptional) λ¬Έμ μ(event) λ°μμ μ§μΉν¨μλ λΆκ΅¬νκ³ λ§μ΄λ€. 80-20 κ·μΉμ(Item 16μμ μΈκΈ) μ°λ¦¬μκ² κ·Έλ° μ΄λ²€νΈλ€μ κ±°μ νλ‘κ·Έλ¨μ λΆκ³Όλλ μ±λ₯μ 컀λ€λ μν₯μ λ―ΈμΉμ§ μμ κ²μ΄λΌκ³ λ§νλ€. κ·ΈλΌμλ λΆκ΅¬νκ³ , λλ λΉμ μ΄ μ΄ λ¬Έμ μ κ΄νμ¬ μμΈλ₯Ό λμ§κ³ , λ°λ λΉμ©μ κ΄ν λλ΅μμ μΌλ§λ ν΄κΉλ₯Ό κΆκΈν κ²μ΄λΌκ³ μκ°νλ€. λκ° μΌλ°μ μΈ ν¨μμ λ°νμμ μμΈλ₯Ό λμ§λ€λ©΄ λμΆ© μΈκ°μ λͺ
λ Ήμ΄ μ λ λ λλ €μ§λ(three order of magnitude) κ²μ΄λΌκ³ κ°μ ν μ μλ€. νμ§λ§ λΉμ μ κ·Έκ²λ§μ΄ μλκ²μ΄λΌκ³ μ΄μΌκΈ° ν κ²μ΄λ€. λ°λλ‘ λΉμ μ΄ μ΄λ° λ
Όμμ λ°μ΄ν° ꡬ쑰λ 루νμ μν ꡬ쑰λ₯Ό ν¨μ¨μ μΌλ‘ λ§λλλ° μ κ²½μ μ΄λ€λ©΄ λ μ’μ μκ°μ 보λ΄λ κ²μ΄λΌκ³ μκ°νλ€.
κ·Έλ μ§λ§ μ κΉ, λ΄κ° μ΄λ°κ²μ κ΄ν΄μ μ΄λ»κ² μλꡬ? λ§μ½ μμΈλ₯Ό μν μ§μμ μ΅κ·Όμ μ»΄νμΌλ¬μ γ·μ»΄νμΌλ¬κ°μ λ€λ₯Έ λ°©μμΌλ‘ μ§νλλ€λ©΄μ λΉμ©μ΄ 5-10%λ¨μ΄μ§κ³ μ€νΌλ μμ λΉμ·νκ² λ¨μ΄μ§κ³ μΈκ° λͺ
λ Ήμ΄ μ λ λμ΄λλ κ²κ³Ό κ°μ μ±λ₯ μ νμ κ΄ν μμ μΈκΈ μ΄λ°κ²μ κ΄ν μΆμ²λ€? μλ§ λ΄κ° ν΄μ€μ μλ λ΅λ³μ λ€μ λλκ²μ΄λ€.:λΉμ μ΄ tryλΈλ‘κ³Ό μμΈ μ€νμ μ¬μ©μ νμν κ³³λ§ μ¬μ©νλλ‘ μ νν΄λΌ;κ·Έλ¦¬κ³ μ»΄νμΌ ν΄λ΄λΌ, κ·Έλλ μ€κ³μμ λ¬Έμ κ° μλ€λ©΄ μΌλ¨ μμ μ μ€κ³λ₯Ό λ€μ κ·Έλ €λ³΄κ³ μκ°ν΄ 보λΌ, κ±°κΈ°μλ€, μ¬κΈ°μ κΈ° λ€λ₯Έ λ²€λλ€μ μ»΄νμΌλ¬λ‘ μ»΄νμΌ ν΄λ΄λΌ κ·ΈλΌ μμ μλ€.