forked from Mooophy/Cpp-Primer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request Mooophy#505 from ZhangZhenghao/master
Add Exerrcise 18.29 19.3 19.4
- Loading branch information
Showing
2 changed files
with
186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |