Skip to content

Commit 0191ae1

Browse files
authored
Merge pull request Mooophy#505 from ZhangZhenghao/master
Add Exerrcise 18.29 19.3 19.4
2 parents 4bf55ae + 2d978bd commit 0191ae1

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

ch18/ex18_29.cpp

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* Exercise 18.29:
2+
3+
Given the following class hierarchy:
4+
5+
class Class { ... }; class Base : public Class { ... };
6+
class D1 : virtual public Base { ... };
7+
class D2 : virtual public Base { ... };
8+
class MI : public D1, public D2 { ... };
9+
class Final : public MI, public Class { ... };
10+
11+
(a) In what order are constructors and destructors run on a Final object?
12+
(b) A Final object has how many Base parts? How many Class parts?
13+
(c) Which of the following assignments is a compile-time error?
14+
15+
Base *pb; Class *pc; MI *pmi; D2 *pd2;
16+
(a) pb = new Class; (b) pc = new Final;
17+
(c) pmi = pb; (d) pd2 = pmi;
18+
19+
Solution:
20+
(a) Constructors run order: Class Base D1 D2 MI Class Final.
21+
Destructors run order: Final Class MI D2 D1 Base Call.
22+
Class parts are constructed from left to right and base class to derived class.
23+
(b) 1 Base part and 2 Class parts.
24+
Because ‘Base’ is a virtual base class of ‘D1’ and ‘D2’. There is only 1 Base part.
25+
However, ‘Class’ is a normal base class of ‘Final’ and ‘Base’. So there is 2 Class part.
26+
(c) error. Can't convert a pointer of base class to a pointer of derived class implicitly.
27+
error. ‘Class’ is an ambiguous base of ‘Final’.
28+
error. Can't convert a pointer of base class to a pointer of derived class implicitly.
29+
pass. A pointer of derived class can be cast to a pointer of base class.
30+
31+
*/
32+
#include <iostream>
33+
34+
using namespace std;
35+
36+
class Class {
37+
public:
38+
Class() { cout << "Class() called" << endl; }
39+
~Class() { cout << "~Class() called" << endl; }
40+
};
41+
42+
class Base : public Class {
43+
public:
44+
Base() { cout << "Base() called" << endl; }
45+
~Base() { cout << "~Base() called" << endl; }
46+
};
47+
48+
class D1 : virtual public Base {
49+
public:
50+
D1() { cout << "D1() called" << endl; }
51+
~D1() { cout << "~D1() called" << endl; }
52+
};
53+
54+
class D2 : virtual public Base {
55+
public:
56+
D2() { cout << "D2() called" << endl; }
57+
~D2() { cout << "~D2() called" << endl; }
58+
};
59+
60+
class MI : public D1, public D2 {
61+
public:
62+
MI() { cout << "MI() called" << endl; }
63+
~MI() { cout << "~MI() called" << endl; }
64+
};
65+
66+
class Final : public MI, public Class {
67+
public:
68+
Final() { cout << "Final() called" << endl; }
69+
~Final() { cout << "~Final() called" << endl; }
70+
};
71+
72+
int main(int argc, char const *argv[])
73+
{
74+
Final final;
75+
Base *pb;
76+
Class *pc;
77+
MI *pmi;
78+
D2 *pd2;
79+
// pb = new Class;
80+
// pc = new Final;
81+
// pmi = pb;
82+
pd2 = pmi;
83+
return 0;
84+
}

ch19/ex19_3_4.cpp

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* Exercises Section 19.2.1
2+
3+
Exercise 19.3:
4+
5+
Given the following class hierarchy in which each class defines a public default constructor and virtual destructor:
6+
7+
class A { . . . };
8+
class B : public A { . . . };
9+
class C : public B { . . . };
10+
class D : public B, public A { . . . };
11+
12+
which, if any, of the following dynamic_casts fail?
13+
(a) A *pa = new C;
14+
B *pb = dynamic_cast< B* >(pa);
15+
(b) B *pb = new B;
16+
C *pc = dynamic_cast< C* >(pb);
17+
(c) A *pa = new D;
18+
B *pb = dynamic_cast< B* >(pa);
19+
20+
Solution:
21+
(a) Succeed. The type of ‘pa’ (class type 'C') is publicly derived from the target type 'B'.
22+
(b) Fail. The type of ‘pb’ (class type 'B') is a public base class of the target type 'C'. ‘pc’ will equal to nullptr.
23+
(c) Fail. ‘A’ is an ambiguous base of ‘D’. Converting a pointer of 'D' to a pointer of 'A' is not allowed.
24+
25+
Exercise 19.4:
26+
27+
Using the classes defined in the first exercise, rewrite the following code to convert the expression *pa to the type C&:
28+
29+
if (C *pc = dynamic_cast< C* >(pa))
30+
// use C's members
31+
} else {
32+
// use A's members
33+
}
34+
35+
Solution:
36+
37+
try {
38+
C &rc = dynamic_cast<C&>(ra);
39+
// use C's members
40+
} catch (bad_cast) {
41+
// use A's members
42+
}
43+
44+
*/
45+
46+
#include <iostream>
47+
#include <typeinfo>
48+
49+
using namespace std;
50+
51+
class A {
52+
public:
53+
virtual ~A() {}
54+
};
55+
56+
class B : public A {
57+
public:
58+
virtual ~B() {}
59+
};
60+
61+
class C : public B {
62+
public:
63+
virtual ~C() {}
64+
};
65+
66+
class D : public B, public A {
67+
public:
68+
virtual ~D() {}
69+
};
70+
71+
int main(int argc, char const *argv[])
72+
{
73+
/* Exercise 19.3 */
74+
75+
A *pa = new C;
76+
B *pb = dynamic_cast< B* >(pa);
77+
if (pb) cout << "19.3 (a) succeed!" << endl;
78+
else cout << "19.3 (a) fail!" << endl;
79+
80+
pb = new B;
81+
C *pc = dynamic_cast< C* >(pb);
82+
if (pc) cout << "19.3 (b) succeed!" << endl;
83+
else cout << "19.3 (b) fail!" << endl;
84+
85+
/* pa = new D;
86+
pb = dynamic_cast< B* >(pa); */
87+
88+
/* Exercise 19.4 */
89+
90+
C c; B b;
91+
A &ra1 = c, &ra2 = b;
92+
try {
93+
/* succeed */
94+
C &rc1 = dynamic_cast<C&>(ra1);
95+
cout << "19.4 succeed!" << endl;
96+
/* fail */
97+
C &rc2 = dynamic_cast<C&>(ra2);
98+
} catch (bad_cast) {
99+
cout << "19.4 failed!" << endl;
100+
}
101+
return 0;
102+
}

0 commit comments

Comments
 (0)