AcceleratedC++/Chapter12 | AcceleratedC++/Chapter14 |
1. Chapter 13 Using inheritance and dynamic binding ¶
13μ₯μμλ 4μ₯μμ λ§λ€μλ μ±μ κ³μ° νλ‘κ·Έλ¨μ νλΆμ, λνμμμ λν΄μ λμνλλ‘ κΈ°λ₯μ νμ₯νλ νλ‘κ·Έλ¨μ ν΅ν΄μ μμκ³Ό λ€νμ±(λμ λ°μΈλ©)μ κ°λ
μ λ°°μ΄λ€.
(9.6μ μ μλ κΈ°μ‘΄μ νλ‘κ·Έλ¨μ μ΄μ©νλ€.)
(9.6μ μ μλ κΈ°μ‘΄μ νλ‘κ·Έλ¨μ μ΄μ©νλ€.)
1.1. 13.1 Inheritance ¶
μμ(inheritance)
λͺ κ°μ§ μΆκ°μ¬νμ μ μΈνλ©΄ νν΄λμ€μ λ€λ₯Έ ν΄λμ€κ° λμΌν κ²½μ°κ° λ§λ€λ λ°μ μ°©μν΄μ λμ¨ κ°λ μ΄λ€.
μ΄ νλ‘κ·Έλ¨μ κ²½μ° κΈ°μ‘΄ κ°μ²΄μ λ€λ₯Έ λΆλΆμ λμΌνμ§λ§ λνμμμ μ±μ μ λ€λ£¨λ κ²½μ°μλ λ Όλ¬Έκ³Ό κ΄λ ¨λ μ μκ° ν¬ν¨λλ€λ κ°μ μ νκ³ λ§λ€μ΄μ§λ€.
λͺ κ°μ§ μΆκ°μ¬νμ μ μΈνλ©΄ νν΄λμ€μ λ€λ₯Έ ν΄λμ€κ° λμΌν κ²½μ°κ° λ§λ€λ λ°μ μ°©μν΄μ λμ¨ κ°λ μ΄λ€.
μ΄ νλ‘κ·Έλ¨μ κ²½μ° κΈ°μ‘΄ κ°μ²΄μ λ€λ₯Έ λΆλΆμ λμΌνμ§λ§ λνμμμ μ±μ μ λ€λ£¨λ κ²½μ°μλ λ Όλ¬Έκ³Ό κ΄λ ¨λ μ μκ° ν¬ν¨λλ€λ κ°μ μ νκ³ λ§λ€μ΄μ§λ€.
λνμμκ³Ό νλΆμμ μ±μ μ 곡ν΅μ μμλ§μ ννν Core Class
~cpp class Core { public: Core(); Core(std::istream&); std::string name() const; std::istream& read(std::istream&); double grade() const; private: std::istream& read_common(std::istream&); std::string n; double midterm, final; std::vector<double> homework; };
λνμμμ κ΄λ ¨λ μ μ μΆκ°ν Grad class
μμλ°μ ν΄λμ€λ κ·Έ λΆλͺ¨ν΄λμ€μ μμ±μ, μλ©Έμ, λμ μ°μ°μλ₯Ό μ μΈν κ·ΈμΈμ λͺ¨λ ν΄λμ€μ μμλ₯Ό λ¬Όλ €λ°λλ€.
λν νμ ν΄λμ€λ λΆλͺ¨ ν΄λμ€μ λ©μλλ₯Ό μ¬μ μ νμ¬μ μμ μκ² λ§λλ‘ μμ νμ¬ λμνλ κ²μ νμ©νλ€.
~cpp class Grad:public Core { // ꡬν(implementation)μ μΌλΆκ° μλ μΈν°νμ΄μ€(interface)μ μΌλΆλ‘μ μμλ°λλ€λ κ²μ λνλ. public: // Coreμ publicμμλ₯Ό κ·Έλλ‘ public μμλ‘ λ°λλ€. Grad(); Grad(std::istream&); double grade() const; std::istream& read(std::istream&); private: double thesis; // λ Όλ¬Έκ΄λ ¨ μ μλ₯Ό μ μ₯νλ λ©€λ²λ³μ }Grad ν΄λμ€λ Coreλ‘ λΆν° νμλμλ€(Derived from), μμλ°μλ€(inherits from), νΉμ Coreλ Gradμ base class μ΄λ€ λΌλ ννμ μ¬μ©νλ€.
μμλ°μ ν΄λμ€λ κ·Έ λΆλͺ¨ν΄λμ€μ μμ±μ, μλ©Έμ, λμ μ°μ°μλ₯Ό μ μΈν κ·ΈμΈμ λͺ¨λ ν΄λμ€μ μμλ₯Ό λ¬Όλ €λ°λλ€.
λν νμ ν΄λμ€λ λΆλͺ¨ ν΄λμ€μ λ©μλλ₯Ό μ¬μ μ νμ¬μ μμ μκ² λ§λλ‘ μμ νμ¬ λμνλ κ²μ νμ©νλ€.
1.1.1. 13.1.1 보νΈμ μ± (protection)μ λν΄μ λ€μ μ΄ν΄λ³΄κΈ° ¶
private λ³΄νΈ λ μ΄λΈλ‘ μ§μ λ λ©€λ²λ κ·Έ ν΄λμ€ μ체, friend ν¨μλ₯Ό ν΅ν΄μλ§ μ§μ μ μΌλ‘ μ κ·Όμ΄ κ°λ₯νλ€. μ΄ κ²½μ° μμλ ν΄λμ€μμλ λΆλͺ¨ ν΄λμ€μ private λ©€λ²λ‘μ μ κ·Όμ΄ νμνλ° μ΄λ΄λ protectedλΌλ ν€μλλ₯Ό μ¬μ©νλ©΄ μ’λ€.
protected λ μ΄λΈλ‘ μ§μ λ λ©€λ²λ€μ μμ ν΄λμ€μμ μ§μ μ μΈ μ κ·Όμ΄ κ°λ₯λ€. κ·Έλ¬λ ν΄λμ€μ μΈλΆμμλ μ κ·Όμ΄ μλκΈ° λλ¬Έμ μΊ‘μνμ μ₯μ μ μ μ§μν¬ μ μλ€.
protected λ μ΄λΈλ‘ μ§μ λ λ©€λ²λ€μ μμ ν΄λμ€μμ μ§μ μ μΈ μ κ·Όμ΄ κ°λ₯λ€. κ·Έλ¬λ ν΄λμ€μ μΈλΆμμλ μ κ·Όμ΄ μλκΈ° λλ¬Έμ μΊ‘μνμ μ₯μ μ μ μ§μν¬ μ μλ€.
~cpp class Core { public: Core(); Core(std::istream&); std::string name() const; double grade() const; std::istream& read(std::istream&); protected: std::istream& read_common(std::istream&); double midterm, final; std::vector<double>homework; private: std::string n;
1.1.2. 13.1.2 μ°μ° ¶
ꡬνν΄μΌν λΆλΆ.
Core, Gradμ μμ±μ 4κ°μ§. κ°κΈ°μ ν΄λμ€μ λ°λΌ λ€λ₯΄κ² νλνκ² λλ read, grade ν¨μ. Core ν΄λμ€μ name, read-common ν¨μ.
Core classμ κΈ°λ³Έ ꡬν
μ΄λ₯Ό λͺ μμ μΌλ‘ νννλ©΄ λ€μκ³Ό κ°μ΄ ννν μ μλ€.
thesisκ° μ μ©λ μ μλ₯Ό 리ν΄νλ Grad::grade() ν¨μ
Core, Gradμ μμ±μ 4κ°μ§. κ°κΈ°μ ν΄λμ€μ λ°λΌ λ€λ₯΄κ² νλνκ² λλ read, grade ν¨μ. Core ν΄λμ€μ name, read-common ν¨μ.
Core classμ κΈ°λ³Έ ꡬν
~cpp string Core::name() const { return n; } double Core::grade() const { return ::grade(midterm. final, homework); } istream& Core::read_common(istream& in) { in>>n>>midterm>>final; return in; } istream& Core::read(istream& in) { read_common(in); read_hw(in, homework); return in; }Grad::read ν¨μμ μ€λ²λ‘λ©
~cpp istream& Grad::read(istream& in) { read_common(in); in >> thesis; read_hw(in, homework); return in; }μκΈ°μ ν΄λμ€λ Gradμ λ©€λ² ν¨μλ‘ λΆλͺ¨ ν΄λμ€μ read_common, read_hwμ ν¨μλ₯Ό κ·Έλλ‘ μμλ°μλ€λ κ²μ κ°μ νλ€.
μ΄λ₯Ό λͺ μμ μΌλ‘ νννλ©΄ λ€μκ³Ό κ°μ΄ ννν μ μλ€.
~cpp istream& Grad::read(istream& in) { Core::read_common(in); in >> thesis; // thesisλ Coreκ° μλλΌ Gradμ λ©€λ² λ³μμ΄λ―λ‘ λ²μ μ§μ μ°μ°μλ₯Ό μ¬μ©ν΄μλ μλλ€. Core::read_hw(in, Core::homework); return in; }
thesisκ° μ μ©λ μ μλ₯Ό 리ν΄νλ Grad::grade() ν¨μ
~cpp double Grad::grade() const { return min(Core::grade(), thesis); // min()μ <algorithm>μ μ μλ ν¨μμ΄λ€. }Core::grade()λ₯Ό μ¬μ©νμ§ μκ³ grade()λ₯Ό μ¬μ©νκ² λλ©΄ Grade:grade()λ₯Όμ¬κ·μ μΌλ‘ νΈμΆνμ¬ μ΄λ€ κ²°κ³Όλ₯Ό 리ν΄ν μ§ μμνμ§ λͺ»νλ€.
1.1.3. 13.1.2 μμ λ° μμ±μ ¶
νμ ν΄λμ€μ μμ±λ¨κ³
λ§μ°¬κ°μ§λ‘ Grad(std::istream&)μ μ΄μ©ν΄μ κ°μ²΄λ₯Ό μ΄κΈ°νν λμλ λΆλͺ¨ κ°μ²΄μ λν΄νΈ μμ±μλ‘ λ¨Όμ κΈ°μ‘΄μ λΆλΆμ μ΄κΈ°ννκ³ , Grad::read(istream&)λ₯Ό ν΅ν΄μ κ° μμμ κ°μ μ΄κΈ°ννκ² λλ€.
* μ 체 κ°μ²΄μ λν 곡κ°μ ν λΉ * κΈ°λ³Έ ν΄λμ€ μμ±μ νΈμΆ, κΈ°λ³Έν΄λμ€ κ³΅κ° μ΄κΈ°ν * μμ±μμ μ΄κΈ°μ€μ μ( ): { μ¬μ΄μ μ‘΄μ¬νλ κ²λ€ )λ₯Ό μ΄μ©ν΄μ νμν΄λμ€μ λ©€λ² μ΄κΈ°ν * νμ ν΄λμ€μ μμ±μμ 본체λ₯Ό μ€ννλ€. |
~cpp class Core { public: Core():midterm(0), final(0) {} Core(std::istream& is) { read(is); } }; class Grad:public Core { public: Grad():thesis(0) {} Grad(std::istream& is) { read(is); } };Gradμ μμ±μλ Coreμ μμ±μκ° midterm, finalμ μ΄κΈ°ν νλ€λ κ°μ νμμ thesisλ§μ μ΄κΈ°ννκ³ μμ΅λλ€. μ΄λ¬ν μ΄κΈ°νλ μ묡μ μΌλ‘ ννμ¬μ§λ€.
λ§μ°¬κ°μ§λ‘ Grad(std::istream&)μ μ΄μ©ν΄μ κ°μ²΄λ₯Ό μ΄κΈ°νν λμλ λΆλͺ¨ κ°μ²΄μ λν΄νΈ μμ±μλ‘ λ¨Όμ κΈ°μ‘΄μ λΆλΆμ μ΄κΈ°ννκ³ , Grad::read(istream&)λ₯Ό ν΅ν΄μ κ° μμμ κ°μ μ΄κΈ°ννκ² λλ€.
1.2. 13.2 Polymorphism and virtual functions ¶
~cpp bool compare(const Core& c1, const Core& c2) { return c1.name() < c2.name(); }
μκΈ°μ ν¨μλ sortμ μν΄μ κ° μμμ νλ¨μμΌλ‘ μ¬μ©λλ ν¨μμ΄λ€. μ΄ ν¨μλ λΆλͺ¨κ°μ²΄μΈ Core κ°μ²΄ λΏλ§μλλΌ, μμ κ°μ²΄μΈ Gradκ°μ²΄λ λμ
νμ¬ μ¬μ©νλ κ²μ΄ κ°λ₯νλ€.
λΉλ‘ ν¨μκ° μꡬνλ μΈμκ°μ Core ν΄λμ€ μ΄μ§λ§ Gradλ Coreλ₯Ό κΈ°λ°μΌλ‘ν΄μ νμλ ν΄λμ€μ΄κΈ° λλ¬Έμ μ΄ κ²½μ° name();λ₯Ό νΈμΆνκ² λλ©΄ g κ°μ²΄μ Core::name() λΆλΆμ΄ νΈμΆλλ€.
λ€μ λ§ν΄μ Gradκ° Coreμ μμ ν΄λμ€ μ΄λ―λ‘ Gradκ°μ²΄λ₯Ό ν΅ν΄μ Coreν΄λμ€μ ν¨μλ₯Ό λ°μΈλ©μμΌ μ¬μ©νλ κ²μ΄ κ°λ₯νλ€λ λ»μ΄λ€. (λμ μ μ΄ ν¨μμ μμμλ Gradμ Core μ μμλ€λ§μ μ·¨νλ€.)
~cpp Grad g(cin); Core c(cin); compare(g, c); // Grad, Coreλ μ½λλ₯Ό λΉκ΅νλ€.Grad ν΄λμ€κ° μ¬μ©κ°λ₯ν μ΄μ
λΉλ‘ ν¨μκ° μꡬνλ μΈμκ°μ Core ν΄λμ€ μ΄μ§λ§ Gradλ Coreλ₯Ό κΈ°λ°μΌλ‘ν΄μ νμλ ν΄λμ€μ΄κΈ° λλ¬Έμ μ΄ κ²½μ° name();λ₯Ό νΈμΆνκ² λλ©΄ g κ°μ²΄μ Core::name() λΆλΆμ΄ νΈμΆλλ€.
λ€μ λ§ν΄μ Gradκ° Coreμ μμ ν΄λμ€ μ΄λ―λ‘ Gradκ°μ²΄λ₯Ό ν΅ν΄μ Coreν΄λμ€μ ν¨μλ₯Ό λ°μΈλ©μμΌ μ¬μ©νλ κ²μ΄ κ°λ₯νλ€λ λ»μ΄λ€. (λμ μ μ΄ ν¨μμ μμμλ Gradμ Core μ μμλ€λ§μ μ·¨νλ€.)
1.2.1. 13.2.1 κ°μ²΄μ νμ μ λͺ¨λ₯΄λ μνμμ κ°μ μ»κΈ° ¶
λ§μ½ μ΄λ¦μ΄ μλλΌ μ΅μ’
μ±μ μ κ°μ§κ³ λΉκ΅λ₯Ό νκ³ μΆμ κ²½μ°λ₯Ό λ€λ£¨κ² λλ€.
gradeμ μ μ¬ν κΈ°λ₯μ νλ compare_grade ν¨μ
μ΄λ° νλμ ν¨μμ μ λ¬λλ νμ¬μ μΈμκ° λ¬΄μμ΄λμ λ°λΌμ λ€λ₯΄κ² κ²°μ λμ΄μΌ νλ―λ‘ μ€νμ(runtime)μ κ²°μ λμ΄μΌ ν κ²μ΄λ€.
λμ λ°μΈλ©μ μν virtualν€μλ
gradeμ μ μ¬ν κΈ°λ₯μ νλ compare_grade ν¨μ
~cpp bool compare_grade(const Core& c1, const Core& c2) { return c1.grade() < c2.grade(); }λ§μ½ μ ν¨μμ μΈμλ‘ μ λ¬λ κ°μ²΄κ° Gradκ°μ²΄λΌλ©΄ κ·Έ κ°μ²΄μμ νΈμΆλλ gradeλ Core::grade() μ΄μ΄μλ μλλ€. κ·Έλ κ² νΈμΆλ κ²½μ° λ Όλ¬Έ μ μκ° μ μ©λμ§ μμ μ±μ λ₯Ό 리ν΄νκΈ° λλ¬Έμ΄λ€. λ°λΌμ Grad::grade() μ ν¨μλ₯Ό νΈμΆν΄μΌ ν κ²μ΄λ€.
μ΄λ° νλμ ν¨μμ μ λ¬λλ νμ¬μ μΈμκ° λ¬΄μμ΄λμ λ°λΌμ λ€λ₯΄κ² κ²°μ λμ΄μΌ νλ―λ‘ μ€νμ(runtime)μ κ²°μ λμ΄μΌ ν κ²μ΄λ€.
λμ λ°μΈλ©μ μν virtualν€μλ
~cpp class Core { public: virtual double grade() const; // virtual μ΄ μΆκ°λ¨. };virtual ν€μλλ‘ μ§μ λ ν¨μλ μ€μ λ‘ ν¨μκ° νΈμΆλ λ κ·Έ κ°μ²΄μ μ΄λ¦ λ²μμ μ‘΄μ¬νλ ν¨μλ₯Ό νΈμΆνλ κ²μ΄ κ°λ₯νλ€.
1.2.2. 13.2.2 λμ λ°μΈλ©(Dynamic binding) ¶
λμ λ°μΈλ©μ΄ μνλκΈ° μν΄μλ μ λ¬μΈμλ‘ μ λ¬λ κ°μ΄ ν¬μΈν°, μ°Έμ‘°μ΄μ΄μΌ κ°λ₯νλ€.
λ§μ½ μΌλ°νμ λ³μλ‘ virtualν¨μλ₯Ό νΈμΆνλ©΄ κ°μ²΄κ° νμ νκ°μ§ νμ μΌλ‘λ§ μ‘΄μ¬νκΈ° λλ¬Έμ μ μ λ°μΈλ©μ΄ λλ€. κ·Έλ¬λ ν¬μΈν°, μ°Έμ‘°νμ κ²½μ° μ΄λ κ² ν λμλ λμ λ°μΈλ©μΌλ‘ λμνκ² λλ€. ν¬μΈν°μ νκ³Ό μ€μ ν¬μΈν°κ° κ°λ¦¬ν€λ λ°μ΄ν°νμ΄ λ€λ₯ΈμΌμ΄ μκΈ°κΈ° λλ¬Έμ΄λ€. λ°λΌμ μ΄ κ²½μ° virtual λ©€λ²ν¨μλ λ°νμμ λμ μΌλ‘ λ°μΈλ© λλ€.
λμ virtual ν€μλλ‘ μ§μ λ ν¨μλ νμ ν΄λμ€μμ λ°λμ μ¬μ μ λμ΄μΌνλ€λ νΉμ§μ΄ μλ€.
λ€νμ±(polymorphism)
κΈ°λ³Έ νμ μ λν ν¬μΈν°λ λ νΌλ°μ€κ° νμν κ³³μ νμ νμ μ μ¬μ©ν μ μλ€λ κ°λ . νλμ νμ μ ν΅ν΄μ μ¬λ¬ ν¨μλ€ μ€ νλλ₯Ό μ ννμ¬ νΈμΆν μ μλ€.
~cpp bool compare_grades(Core c1, Core c2) { return c1.grade() < c2.grade(); }μκΈ°μ κ²½μ° Grad κ°μ²΄λ₯Ό μΈμλ‘ μ λ¬ν κ²½μ° Gradκ°μ²΄μ Coreκ°μ²΄μ μμλ§ λ³΅μ¬λμ΄ ν¨μμ μΈμλ‘ μ λ¬λκΈ° λλ¬Έμ Core::grade()κ° νΈμΆλμ΄μ μ μ λ°μΈλ©(static binding)μ΄ μνλλ€.
λ§μ½ μΌλ°νμ λ³μλ‘ virtualν¨μλ₯Ό νΈμΆνλ©΄ κ°μ²΄κ° νμ νκ°μ§ νμ μΌλ‘λ§ μ‘΄μ¬νκΈ° λλ¬Έμ μ μ λ°μΈλ©μ΄ λλ€. κ·Έλ¬λ ν¬μΈν°, μ°Έμ‘°νμ κ²½μ° μ΄λ κ² ν λμλ λμ λ°μΈλ©μΌλ‘ λμνκ² λλ€. ν¬μΈν°μ νκ³Ό μ€μ ν¬μΈν°κ° κ°λ¦¬ν€λ λ°μ΄ν°νμ΄ λ€λ₯ΈμΌμ΄ μκΈ°κΈ° λλ¬Έμ΄λ€. λ°λΌμ μ΄ κ²½μ° virtual λ©€λ²ν¨μλ λ°νμμ λμ μΌλ‘ λ°μΈλ© λλ€.
λμ virtual ν€μλλ‘ μ§μ λ ν¨μλ νμ ν΄λμ€μμ λ°λμ μ¬μ μ λμ΄μΌνλ€λ νΉμ§μ΄ μλ€.
λ€νμ±(polymorphism)
κΈ°λ³Έ νμ μ λν ν¬μΈν°λ λ νΌλ°μ€κ° νμν κ³³μ νμ νμ μ μ¬μ©ν μ μλ€λ κ°λ . νλμ νμ μ ν΅ν΄μ μ¬λ¬ ν¨μλ€ μ€ νλλ₯Ό μ ννμ¬ νΈμΆν μ μλ€.
1.2.3. 13.2.2 μμ½ ¶
~cpp #ifndef GUARD_Core_h #define GUARD_Core_h #include <iostream> #include <stdexcept> #include <string> #include <vector> class Core { public: Core(): midterm(0), final(0) { } Core(std::istream& is) { read(is); } std::string name() const; // as defined in 13.1.2/230 virtual std::istream& read(std::istream&); // virtual ν€μλλ‘ μ μλ ν¨μλ λ°λμ μ¬μ μλμ΄μΌνλ€. virtual double grade() const; protected: // accessible to derived classes std::istream& read_common(std::istream&); double midterm, final; std::vector<double> homework; private: // accessible only to `Core' std::string n; }; class Grad: public Core { public: Grad(): thesis(0) { } Grad(std::istream& is) { read(is); } // as defined in 13.1.2/230; Note: `grade' and `read' are `virtual' by inheritance double grade() const; std::istream& read(std::istream&); private: double thesis; }; bool compare(const Core&, const Core&); #endif
1.3. 13.3 Using inheritance to solve our problem ¶
λ§λ€μ΄μ§ ν΄λμ€λ₯Ό μ΄μ©ν΄μ μ±μ μ μ
λ ₯λ°κ³ λ³΄κ³ μλ₯Ό μΆλ ₯νλ νλ‘κ·Έλ¨ (Core)
~cpp int main() { vector<Core> students; Core record; // Coreμ μΌλ°ν string::size_type maxlen = 0; while(record.read(cin)) { maxlen = max(maxlen, record.name().size()); students.push_back(record); } sort(students.begin(), students.end(), compare); for (vector<Core>::size_type i = 0; i != students.size(); ++i) { cout<<students[i].name() <<string(maxlen + 1 - students[i].name.size(), ' '); try { double final_grade = students[i].grade(); streamsize prec = cout.precision(); cout<<setprecision(3)<<final_grade <<setprecision(prec)<<endl; } catch (domain_error e) { cout<<e.what()<<endl; } } return 0; }
λ§λ€μ΄μ§ ν΄λμ€λ₯Ό μ΄μ©ν΄μ μ±μ μ μ
λ ₯λ°κ³ λ³΄κ³ μλ₯Ό μΆλ ₯νλ νλ‘κ·Έλ¨ (Grad)
μ΄λ κ² νλ‘κ·Έλ¨μ΄ μμ±λλ©΄ λμΌν κΈ°λ₯μ νλ νλ‘κ·Έλ¨μ μλ£νμ λ°λΌμ 2κ°μ§λ‘ λ°λ‘ μμ±ν΄μΌνλ€.
~cpp int main() { vector<Grad> students; Grad record; // Gradμ μΌλ°ν string::size_type maxlen = 0; while(record.read(cin)) { maxlen = max(maxlen, record.name().size()); students.push_back(record); } sort(students.begin(), students.end(), compare); for (vector<Grad>::size_type i = 0; i != students.size(); ++i) { cout<<students[i].name() <<string(maxlen + 1 - students[i].name.size(), ' '); try { double final_grade = students[i].grade(); streamsize prec = cout.precision(); cout<<setprecision(3)<<final_grade <<setprecision(prec)<<endl; } catch (domain_error e) { cout<<e.what()<<endl; } } return 0; }μ λ ₯μ λ°λ recordκ° μΌλ°νμ΄κΈ° λλ¬Έμ μμ 2κ°μ νλ‘κ·Έλ¨μ κ°κΈ° Core, Gradμ λν΄μ μ μ μΌλ‘ λ°μΈλ©λλ€.
μ΄λ κ² νλ‘κ·Έλ¨μ΄ μμ±λλ©΄ λμΌν κΈ°λ₯μ νλ νλ‘κ·Έλ¨μ μλ£νμ λ°λΌμ 2κ°μ§λ‘ λ°λ‘ μμ±ν΄μΌνλ€.
λ¨μΌνλ‘κ·Έλ¨μ μμ±νκΈ°μν΄μ νμ
μμ‘΄μ±μ μ κ±°ν΄μΌν λΆλΆ
λ§μ§λ§ 2κ°μ§ λ¬Έμ λ virtualλ‘ μ μλ λ©€λ²ν¨μλ₯Ό ν΅ν΄μ ν΄κ²°. μ²μμ 2κ°μ§λ₯Ό ν΄κ²°νλ λ°©λ²μ 2κ°μ§κ° μ‘΄μ¬νλ©° 13.3~13.4μ μ κ±Έμ³μ μ€λͺ
νλ€.
* μ½μ΄λ€μΌ μμλ€μ μ μ₯νλ vectorμ μ μ * λ μ½λλ₯Ό μ½μ΄λ€μΌ μμ μ§μ λ³μμ μ μ * read ν¨μ * grade ν¨μ |
1.3.1. 13.3.1 μμ§ λͺ»νλ(κ°μμ μΌλ‘) νμ μ λν 컨ν μ΄λ ¶
μμ μμμμ²λΌ vector<Core>μ 컨ν
μ΄λλ₯Ό μ€μ νκ² λλ©΄ 컨ν
μ΄λ μμ μ μ₯λλ κ°μ²΄κ° Coreμ κ°μ²΄κ° λλ―λ‘ μ μ μΌλ‘ λ°μΈλ©λλ€. μ΄λ₯Ό ν΄κ²°νκΈ° μν΄μλ vector<Core*>λ₯Ό ν΅ν΄μ κ°μ²΄λ₯Ό λμ μΌλ‘ ν λΉνκ³ κ΄λ¦¬νλλ‘ νλ©΄, μλ‘ λ€λ₯Έ νμ
μ κ°μ²΄λ₯Ό μ μ₯νλ κ²λ κ°λ₯νκ³ νλ‘κ·Έλ¨μ λ€λ₯Έ λΆλΆμμ λ€νμ±μ μ΄μ μ μ΄μ©νλ κ²λ κ°λ₯νλ€.
ν¬μΈν°λ‘ μ΄λ£¨μ΄μ§ κ°μ²΄λ₯Ό λΉκ΅νκΈ° μν΄μ μμ±ν ν¨μ
~cpp int main() { vector<Core*> students; Core* record; while (record->read(cin)) { //... } }μμ νλ‘κ·Έλ¨μ ν λΉλμ§ μμ Core 곡κ°μ κ°μ λμ νλ €νκΈ° λλ¬Έμ μλ¬λ₯Ό λ°μμν¨λ€. νλ‘κ·Έλλ¨Έκ° κ°μ²΄μ νμν 곡κ°μ μ§μ κ΄λ¦¬. μ½μ΄λ€μ΄λ λ μ½λμ μ’ λ₯λ₯Ό νλ¨ν΄μΌν¨.
ν¬μΈν°λ‘ μ΄λ£¨μ΄μ§ κ°μ²΄λ₯Ό λΉκ΅νκΈ° μν΄μ μμ±ν ν¨μ
~cpp bool compare_Core_ptrs(const Core* cp1, const Core* cp2) { return compare(*cp1, *cp2); }μΈμλ₯Ό μ λ¬νλ©΄μ μκΈ°λ λͺ¨νΈν¨μ νΌνκΈ° μν΄μ compare λΌλ μ΄λ¦λμ μ compare_Core_ptrsλ₯Ό μ¬μ©νμ¬ μ»΄νμΌλ¬κ° λͺ μμ μΌλ‘ μ΄ ν¨μλ₯Ό μ¬μ©νλλ‘ νλ€.
~cpp // main_core.cpp #include <vector> #include <string> #include <algorithm> #include <iomanip> #include <ios> #include <iostream> #include <stdexcept> #include "Core.h" using std::cout; using std::cin; using std::domain_error; using std::endl; using std::setprecision; using std::setw; using std::streamsize; using std::sort; using std::string; using std::vector; using std::max; // this code almost works; see 13.3.2/242 int main() { vector<Core*> students; // store pointers, not objects Core* record; // temporary must be a pointer as well char ch; string::size_type maxlen = 0; // read and store the data while (cin >> ch) { if (ch == 'U') record = new Core; // allocate a `Core' object else record = new Grad; // allocate a `Grad' object record->read(cin); // `virtual' call maxlen = max(maxlen, record->name().size());// dereference students.push_back(record); } // pass the version of `compare' that works on pointers sort(students.begin(), students.end(), compare_Core_ptrs); // write the names and grades for (vector<Core*>::size_type i = 0; i != students.size(); ++i) { // `students[i]' is a pointer that we dereference to call the functions cout << students[i]->name() << string(maxlen + 1 - students[i]->name().size(), ' '); try { double final_grade = students[i]->grade(); streamsize prec = cout.precision(); cout << setprecision(3) << final_grade << setprecision(prec) << endl; } catch (domain_error e) { cout << e.what() << endl; } delete students[i]; // free the object allocated when reading } return 0; }μ λ ₯κ³Ό μΆλ ₯μ κ° λΆλΆμμ κ·Έλ¦¬κ³ μ»¨ν μ΄λμ μμλ₯Ό μ¬μ©ν λ ν¬μΈν°λ₯Ό μ΄μ©ν¨μΌλ‘ν΄μ νλ‘κ·Έλ¨μ΄ λμ λ°μΈλ©μ μ΄μ©ν΄μ μλΉν κ°κ²°ν΄μ§ κ²μ νμΈν μ μλ€.
1.3.2. 13.3.2 κ°μ μλ©Έμ(virtual destructor) ¶
μκΈ°μ κ°μ ꡬ쑰μμλ studentsiμ νμ
μ΄ Core* μ΄κΈ° λλ¬Έμ λ©λͺ¨λ¦¬ ν΄μ μμ Coreλ²μ μ μλ©Έμκ° νΈμΆλκ³ Grad λΆλΆμ ν΄μ λμ§ μλλ€.
μλ©Έμ μμλ virtual ν¨μλ‘ λ§λ€μ΄μ λμ νμ μ λ°λΌ λ€λ₯Έ λμμ±μ 보μ₯νλ κ²μ΄ κ°λ₯νλ€.
μλ©Έμ μμλ virtual ν¨μλ‘ λ§λ€μ΄μ λμ νμ μ λ°λΌ λ€λ₯Έ λμμ±μ 보μ₯νλ κ²μ΄ κ°λ₯νλ€.
~cpp class Core { public: virtual ~Core() { } //μ΄μ κ³Ό λμΌ };μκΈ°μ κ°μ΄ λΉ μλ©Έμλ₯Ό μ¬μ©νλ κ²μ νν κ²½μ°μ΄λ€. κΈ°λ³Έ νμ μ μλ©Έμλ₯Ό virtual λ‘ λ§λ¦μΌλ‘μ νμ ν΄λμ€μμ λ°μνλ κΈ°ν μμλ€μ ν΄μ ν΄μΌν κ²½μ°κ° λ§κΈ° λλ¬Έμ΄λ€.
1.4. 13.4 A simple handle class ¶
μκΈ°μ κ°μ λ°©μμΌλ‘ ν¬μΈν°λ₯Ό μ΄μ©ν΄μ νλ‘κ·Έλ¨μ μμ±νκ² λλ©΄ νλ‘κ·Έλλ¨Έκ° λ©λͺ¨λ¦¬λ₯Ό μ§μ μ μΌλ‘ κ΄λ¦¬λ₯Ό ν΄μΌνκΈ° λλ¬Έμ μ¬λ¬κ°μ§ λ²κ·Έλ₯Ό λ§λλ λ¬Έμ μ μ κ°μ§κ³ μλ€.
νΈλ€ ν΄λμ€(handle class)
νΉμ νμ ν¬μΈν°λ₯Ό μΊ‘μνμν¨ μΈν°νμ΄μ€λ₯Ό μ 곡ν΄μ, νλ‘κ·Έλλ¨Έμκ² ν¬μΈν°κ° 보μ΄μ§ μλλ‘ νλ λ°©λ²μ μ 곡νλ€.
μ μ λ©€λ²ν¨μ(static member fuction)
μΌλ° λ©€λ² ν¨μμλ λ¬λ¦¬ κ·Έ ν΄λμ€ νμ μ κ°μ²΄μ λν΄ μμ μ μννλ κ²μ΄ μλκ³ , ν΄λμ€ μμμλ ν΄λμ€ κ°μ²΄μ μ μ λ°μ΄ν° λ©€λ²λ§μ λ€λ£¨λ κ²μ΄ κ°λ₯νλ€.
μ₯μ μΌλ‘λ μμ λ²μλ₯Ό κ·Έ ν΄λμ€μ λ²μλ§νΌμ κ°μ§κΈ° λλ¬Έμ ν΄λμ€ λ΄λΆμμ μ¬μ©λ λ ::compareμ νΌλλ μΌλ €κ° μλ€λ κ²μ΄λ€.
νΈλ€ ν΄λμ€(handle class)
νΉμ νμ ν¬μΈν°λ₯Ό μΊ‘μνμν¨ μΈν°νμ΄μ€λ₯Ό μ 곡ν΄μ, νλ‘κ·Έλλ¨Έμκ² ν¬μΈν°κ° 보μ΄μ§ μλλ‘ νλ λ°©λ²μ μ 곡νλ€.
~cpp //Student_info.h #ifndef GUARD_Student_info_h #define GUARD_Student_info_h #include <iostream> #include <stdexcept> #include <string> #include <vector> #include "Core.h" class Student_info { public: // constructors and copy control Student_info(): cp(0) { } Student_info(std::istream& is): cp(0) { read(is); } Student_info(const Student_info&); Student_info& operator=(const Student_info&); ~Student_info() { delete cp; } // operations std::istream& read(std::istream&); std::string name() const { if (cp) return cp->name(); else throw std::runtime_error("uninitialized Student"); } double grade() const { if (cp) return cp->grade(); else throw std::runtime_error("uninitialized Student"); } static bool compare(const Student_info& s1, const Student_info& s2) { // μ μ λ©€λ² ν¨μμ μ μΈ return s1.name() < s2.name(); } private: Core* cp; }; #endifCore*λ₯Ό Student_infoλ₯Ό ν΅ν΄μ Wrapping μν΄μΌλ‘μ¨ νλ‘κ·Έλλ¨Έλ μ€μ λ‘λ₯΄ Student_infoκ° 2κ°μ§ μ’ λ₯μ κ°μ²΄λ₯Ό λ€λ£° μ μμ§λ§ μ€μ μ λ΄λΆ ꡬνμ μμ§ λͺ»νκ² λλ€.
μ μ λ©€λ²ν¨μ(static member fuction)
μΌλ° λ©€λ² ν¨μμλ λ¬λ¦¬ κ·Έ ν΄λμ€ νμ μ κ°μ²΄μ λν΄ μμ μ μννλ κ²μ΄ μλκ³ , ν΄λμ€ μμμλ ν΄λμ€ κ°μ²΄μ μ μ λ°μ΄ν° λ©€λ²λ§μ λ€λ£¨λ κ²μ΄ κ°λ₯νλ€.
μ₯μ μΌλ‘λ μμ λ²μλ₯Ό κ·Έ ν΄λμ€μ λ²μλ§νΌμ κ°μ§κΈ° λλ¬Έμ ν΄λμ€ λ΄λΆμμ μ¬μ©λ λ ::compareμ νΌλλ μΌλ €κ° μλ€λ κ²μ΄λ€.
1.4.1. 13.4.1 νΈλ€ μ½κΈ° ¶
~cpp istream& Student_info::read(istream& is) { delete cp; // μΈμ΄μ μΌλ‘ λν¬μΈν°λ₯Ό ν΄μ νλ κ²μ λ¬Έμ κ° μμΌλ―λ‘ μ²΄ν¬νλ μ½λλ₯Ό λ£μ§ μμλ λλ€. char ch; is>>ch; if(ch == 'U') { cp = new Core(is); } else { cp = new Grad(is); } return is; }μ°μ μ 첫λ²μ§Έ μΈμλ₯Ό λ°μμ μμ±ν κ°μ²΄μ νμ μ κ²°μ νκ³ , κ²°μ λ νμ μ κ°μ²΄λ₯Ό μμ±μν¨λ€.
1.4.2. 13.4.2 νΈλ€ κ°μ²΄ λ³΅μ¬ ¶
νμ¬ μνμ ν΄λμ€λ‘λ 볡μ¬μμ±μκ° νμν κ³³μμ κ³Όμ° cpμ ν λΉλ κ°μ²΄κ° GradμΈμ§ CoreμΈμ§λ₯Ό νμΈν λ°©λ²μ΄ μλ€.
μ΄λ₯Ό ν΄κ²°νλ κ²μ λ³΅μ¬ μμ±μλ₯Ό virtual λ‘ ν λΉνκ³ μ΄λ¬ν μΌμ μ»΄νμΌλ¬μκ² μμμν€λ λ°©λ²μ΄λ€.
Student_info ν΄λμ€μμ Grad::clone()λ₯Ό μ§μ μ μΌλ‘ νΈμΆνλ κ²½μ°κ° μκΈ° λλ¬Έμ friendλ‘ μ μΈνμ§ μμλ 무κ΄νλ€.
μ΄λ₯Ό ν΄κ²°νλ κ²μ λ³΅μ¬ μμ±μλ₯Ό virtual λ‘ ν λΉνκ³ μ΄λ¬ν μΌμ μ»΄νμΌλ¬μκ² μμμν€λ λ°©λ²μ΄λ€.
~cpp class Core { friend class Student_info; protected: virtual Core* clone() const { return new Core(*this); } }; class Grad { protected: Grad* clone() const { return new Grad(*this); } // λ³Έλ virtual ν¨μμμλ κΈ°λ³Έν΄λμ€μ νμν΄λμ€μμ // μ€λ²λ‘λνλ ν¨μμ νλΌλ©ν° λͺ μΈ, 리ν΄νμ΄ λμΌν΄μΌνμ§λ§ // ν¬μΈν°νμΈ κ²½μ°μλ νμ ν΄λμ€μ ν¬μΈν°λ₯Ό μ¬μ©νλ κ²μ΄ κ°λ₯νλ€. };friend class Student_info; λ₯Ό μ¬μ©ν¨μΌλ‘ν΄μ Student_infoμ λͺ¨λ λ©€λ²ν¨μλ Coreμ protected, privateμ μ κ·Όνλ κ²μ΄ κ°λ₯νλ€.
Student_info ν΄λμ€μμ Grad::clone()λ₯Ό μ§μ μ μΌλ‘ νΈμΆνλ κ²½μ°κ° μκΈ° λλ¬Έμ friendλ‘ μ μΈνμ§ μμλ 무κ΄νλ€.
~cpp Student_info::Student_info(const Student_info& s) : cp(0) { if (s.cp) cp = s.cp->clone(); } Student_info& Student_info::operator=(const Student_info& s) { if (&s != this) { delete cp; if (s.cp) cp = s.cp->clone(); else cp = 0; { return *this; }
1.5. 13.5 Using the handle class ¶
~cpp //main_perfect.cpp #include <algorithm> #include <iomanip> #include <ios> #include <iostream> #include <stdexcept> #include <string> #include <vector> #include "Student_info.h" using std::cin; using std::cout; using std::domain_error; using std::endl; using std::setprecision; using std::setw; using std::sort; using std::streamsize; using std::string; using std::vector; using std::max; int main() { vector<Student_info> students; Student_info record; string::size_type maxlen = 0; // read and store the data while (record.read(cin)) { maxlen = max(maxlen, record.name().size()); students.push_back(record); } // alphabetize the student records sort(students.begin(), students.end(), Student_info::compare); // write the names and grades for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) { cout << students[i].name() << string(maxlen + 1 - students[i].name().size(), ' '); try { double final_grade = students[i].grade(); streamsize prec = cout.precision(); cout << setprecision(3) << final_grade << setprecision(prec) << endl; } catch (domain_error e) { cout << e.what() << endl; } } return 0; }
μ 체μ μΌλ‘ μ¬μ΄ μμ€μ΄λ―λ‘ μλ΅, λͺ¨λ₯΄λ©΄ μ±
μ μ°Έμ‘°.
1.6.1. 13.6.1 μμ λ° μ»¨ν μ΄λ ¶
vector<Core>κ° κ·Έ νμνμ λ΄μ μ μλ€λ κ²μ μ μνλΌ. (μΌκ²¬ λ κ² μ²λΌ 보μ΄μ§λ§ μλλ€)
μνλ λ°©μλλ‘ λμνλ κ²μΈμ§ μλμ§λ νλ‘κ·Έλλ¨Έμ μλμ λ¬λ €μλ€.
~cpp vector<Core> students; Grad g(cin); students.push_back(g);μ ν¨ν ννμ΄κΈ°λ νμ§λ§ gμ Coreν΄λμ€μμ μ μλ λΆλΆ λ§μ΄ μ μ₯μ΄ λλ€.
μνλ λ°©μλλ‘ λμνλ κ²μΈμ§ μλμ§λ νλ‘κ·Έλλ¨Έμ μλμ λ¬λ €μλ€.
1.6.2. 13.6.2 μ΄λ€ ν¨μλ₯Ό μνλμ? ¶
λ§μ½ λΆλͺ¨ ν΄λμ€μ μλ λ©μλμ λ©μλ λͺ
μ κ°μ§λ§ νλΌλ©ν°λ νμ
μ΄ κ°μ΄ μμΌλ©΄ λ©μλλ μμ ν λ€λ₯Έ ν¨μλ‘ μΈμλμ΄ μλνλ€.
~cpp //λ§μ½ rμ΄ Coreμ κ°μ²΄μ΄κ³ Core::regrade(double)λ μΈμλ‘ λ°μ κ²μ finalμ κΈ°λ‘νλ€. //Grad::regrade(double, double) μΈμλ‘ λ°μκ°μΌλ‘ final, thesisλ₯Ό ν λΉ r.regrade(100); // μλ r.regrade(100, 100); // μ»΄νμΌ μ€λ₯
~cpp //λ§μ½ rμ΄ Gradμ κ°μ²΄μ΄κ³ Core::regrade(double)λ μΈμλ‘ λ°μ κ²μ finalμ κΈ°λ‘νλ€. //Grad::regrade(double, double) μΈμλ‘ λ°μκ°μΌλ‘ final, thesisλ₯Ό ν λΉ r.regrade(100); // μ»΄νμΌ μ€λ₯. Grad::compare λ₯Ό κΈ°λνκΈ° λλ¬Έμ μ΄λ° λ¬Έμ κ° λ°μνλ€. r.Core::regrade(100); // μλ. λ²μ μ°μ°μλ₯Ό μ΄μ©ν΄μ λͺ μμ μΌλ‘ νΈμΆνλ κ²μ νμ©νλ€. r.regrade(100, 100); // μλ.
~cpp virtual void Core::regrade(double d, double =0) { final = d; }λ§μ½ μ΄λ° ν¨μλ₯Ό virtual λ‘ μ μνκ³ μΆλ€λ©΄ μ¬μ©νμ§ μλ μΈμλ₯Ό λν΄νΈ μΈμλ‘ μ§μ ν΄μ λ§λ€λ©΄ λλ€.