From 70247e7137f3891c4852b2063e0fbb560b604819 Mon Sep 17 00:00:00 2001 From: ZhangZhenghao Date: Tue, 20 Sep 2016 09:47:06 +0800 Subject: [PATCH 1/2] Add Exerrcise 19.3 and Exercise 19.4 --- ch19/ex19_3_4.cpp | 102 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 ch19/ex19_3_4.cpp diff --git a/ch19/ex19_3_4.cpp b/ch19/ex19_3_4.cpp new file mode 100644 index 00000000..f51b9002 --- /dev/null +++ b/ch19/ex19_3_4.cpp @@ -0,0 +1,102 @@ +/* Exercises Section 19.2.1 + +Exercise 19.3: + +Given the following class hierarchy in which each class defines a public default constructor and virtual destructor: + +class A { . . . }; +class B : public A { . . . }; +class C : public B { . . . }; +class D : public B, public A { . . . }; + +which, if any, of the following dynamic_casts fail? +(a) A *pa = new C; + B *pb = dynamic_cast< B* >(pa); +(b) B *pb = new B; + C *pc = dynamic_cast< C* >(pb); +(c) A *pa = new D; + B *pb = dynamic_cast< B* >(pa); + +Solution: +(a) Succeed. The type of ‘pa’ (class type 'C') is publicly derived from the target type 'B'. +(b) Fail. The type of ‘pb’ (class type 'B') is a public base class of the target type 'C'. ‘pc’ will equal to nullptr. +(c) Fail. ‘A’ is an ambiguous base of ‘D’. Converting a pointer of 'D' to a pointer of 'A' is not allowed. + +Exercise 19.4: + +Using the classes defined in the first exercise, rewrite the following code to convert the expression *pa to the type C&: + +if (C *pc = dynamic_cast< C* >(pa)) + // use C's members +} else { + // use A's members +} + +Solution: + +try { + C &rc = dynamic_cast(ra); + // use C's members +} catch (bad_cast) { + // use A's members +} + +*/ + +#include +#include + +using namespace std; + +class A { +public: + virtual ~A() {} +}; + +class B : public A { +public: + virtual ~B() {} +}; + +class C : public B { +public: + virtual ~C() {} +}; + +class D : public B, public A { +public: + virtual ~D() {} +}; + +int main(int argc, char const *argv[]) +{ + /* Exercise 19.3 */ + + A *pa = new C; + B *pb = dynamic_cast< B* >(pa); + if (pb) cout << "19.3 (a) succeed!" << endl; + else cout << "19.3 (a) fail!" << endl; + + pb = new B; + C *pc = dynamic_cast< C* >(pb); + if (pc) cout << "19.3 (b) succeed!" << endl; + else cout << "19.3 (b) fail!" << endl; + +/* pa = new D; + pb = dynamic_cast< B* >(pa); */ + + /* Exercise 19.4 */ + + C c; B b; + A &ra1 = c, &ra2 = b; + try { + /* succeed */ + C &rc1 = dynamic_cast(ra1); + cout << "19.4 succeed!" << endl; + /* fail */ + C &rc2 = dynamic_cast(ra2); + } catch (bad_cast) { + cout << "19.4 failed!" << endl; + } + return 0; +} \ No newline at end of file From 2d978bddfdfe60d35099dcf7857fe60cc8d6e800 Mon Sep 17 00:00:00 2001 From: ZhangZhenghao Date: Tue, 20 Sep 2016 16:40:31 +0800 Subject: [PATCH 2/2] Add Exercise 18.29 --- ch18/ex18_29.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 ch18/ex18_29.cpp diff --git a/ch18/ex18_29.cpp b/ch18/ex18_29.cpp new file mode 100644 index 00000000..38143b8d --- /dev/null +++ b/ch18/ex18_29.cpp @@ -0,0 +1,84 @@ +/* Exercise 18.29: + +Given the following class hierarchy: + +class Class { ... }; class Base : public Class { ... }; +class D1 : virtual public Base { ... }; +class D2 : virtual public Base { ... }; +class MI : public D1, public D2 { ... }; +class Final : public MI, public Class { ... }; + +(a) In what order are constructors and destructors run on a Final object? +(b) A Final object has how many Base parts? How many Class parts? +(c) Which of the following assignments is a compile-time error? + +Base *pb; Class *pc; MI *pmi; D2 *pd2; +(a) pb = new Class; (b) pc = new Final; +(c) pmi = pb; (d) pd2 = pmi; + +Solution: +(a) Constructors run order: Class Base D1 D2 MI Class Final. + Destructors run order: Final Class MI D2 D1 Base Call. + Class parts are constructed from left to right and base class to derived class. +(b) 1 Base part and 2 Class parts. + Because ‘Base’ is a virtual base class of ‘D1’ and ‘D2’. There is only 1 Base part. + However, ‘Class’ is a normal base class of ‘Final’ and ‘Base’. So there is 2 Class part. +(c) error. Can't convert a pointer of base class to a pointer of derived class implicitly. + error. ‘Class’ is an ambiguous base of ‘Final’. + error. Can't convert a pointer of base class to a pointer of derived class implicitly. + pass. A pointer of derived class can be cast to a pointer of base class. + +*/ +#include + +using namespace std; + +class Class { +public: + Class() { cout << "Class() called" << endl; } + ~Class() { cout << "~Class() called" << endl; } +}; + +class Base : public Class { +public: + Base() { cout << "Base() called" << endl; } + ~Base() { cout << "~Base() called" << endl; } +}; + +class D1 : virtual public Base { +public: + D1() { cout << "D1() called" << endl; } + ~D1() { cout << "~D1() called" << endl; } +}; + +class D2 : virtual public Base { +public: + D2() { cout << "D2() called" << endl; } + ~D2() { cout << "~D2() called" << endl; } +}; + +class MI : public D1, public D2 { +public: + MI() { cout << "MI() called" << endl; } + ~MI() { cout << "~MI() called" << endl; } +}; + +class Final : public MI, public Class { +public: + Final() { cout << "Final() called" << endl; } + ~Final() { cout << "~Final() called" << endl; } +}; + +int main(int argc, char const *argv[]) +{ + Final final; + Base *pb; + Class *pc; + MI *pmi; + D2 *pd2; + // pb = new Class; + // pc = new Final; + // pmi = pb; + pd2 = pmi; + return 0; +} \ No newline at end of file