Skip to content

Commit

Permalink
Merge pull request Mooophy#505 from ZhangZhenghao/master
Browse files Browse the repository at this point in the history
Add Exerrcise 18.29 19.3 19.4
  • Loading branch information
Mooophy authored Sep 25, 2017
2 parents 4bf55ae + 2d978bd commit 0191ae1
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 0 deletions.
84 changes: 84 additions & 0 deletions ch18/ex18_29.cpp
Original file line number Diff line number Diff line change
@@ -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 <iostream>

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;
}
102 changes: 102 additions & 0 deletions ch19/ex19_3_4.cpp
Original file line number Diff line number Diff line change
@@ -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<C&>(ra);
// use C's members
} catch (bad_cast) {
// use A's members
}
*/

#include <iostream>
#include <typeinfo>

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<C&>(ra1);
cout << "19.4 succeed!" << endl;
/* fail */
C &rc2 = dynamic_cast<C&>(ra2);
} catch (bad_cast) {
cout << "19.4 failed!" << endl;
}
return 0;
}

0 comments on commit 0191ae1

Please sign in to comment.