2727//
2828// License: MIT
2929// ========================================================================
30+ #include " cppt_tools.hpp"
31+ #include " cppt_ag.hpp"
32+
3033#include < cstdint>
3134#include < iostream>
3235#include < typeinfo>
3336
34- #include " cppt_ag.hpp"
3537
3638// ========================================================================
3739// Data structures
3840// ========================================================================
3941// ------------------------------------------------------------------------
40- // A and B are related through B's constructors
42+ // A and B are related through B's constructors - NON-VIRTUAL
4143// ------------------------------------------------------------------------
4244struct A {
4345 A () { std::cout << " A()" << std::endl; }
@@ -49,7 +51,7 @@ struct B {
4951};
5052
5153// ------------------------------------------------------------------------
52- // C is unrelated to A and B
54+ // C is unrelated to A and B - NON-VIRTUAL
5355// ------------------------------------------------------------------------
5456struct C {
5557 C (int32_t a, int32_t b) : x(a), y(b) {
@@ -63,7 +65,8 @@ struct C {
6365};
6466
6567// ------------------------------------------------------------------------
66- // E inherits from D (note that it contains data not present in D)
68+ // E inherits from D - VIRTUAL
69+ // (note that E contains data not present in D)
6770// ------------------------------------------------------------------------
6871struct D {
6972 D () { std::cout << " D()" << std::endl; }
@@ -80,31 +83,61 @@ struct E : public D {
8083 int32_t some_int = 123 ;
8184};
8285
86+ // ------------------------------------------------------------------------
87+ // Unrelated classes - VIRTUAL
88+ // ------------------------------------------------------------------------
89+
90+ struct F {
91+ virtual int g () {return 4 ;}
92+ };
93+
94+ struct G {
95+ virtual int h () {return 6 ;}
96+ };
97+
8398// ========================================================================
8499// main
85100// ========================================================================
86- int main () {
101+ int main (int argc, const char ** argv) {
102+ cppt::header (argv[0 ]);
103+ size_t sec_num = {1 };
104+
105+ // -------------------------------------------------------------------------
87106 // 1. ===> IMPLICIT CONVERSION <===
88- std::cout << " 1. IMPLICIT CONVERSION:" << std::endl;
107+ // -------------------------------------------------------------------------
108+ std::cout << " ========================================================" << std::endl;
109+ std::cout << " ===> IMPLICIT CONVERSION <===" << std::endl;
110+ std::cout << " ========================================================" << std::endl;
111+ std::cout << sec_num++ << " . Cost through constructors:" << std::endl;
89112
90- // 1.1 Cast between different integer types
113+ // Cast between different integer types
91114 int16_t var_a = 2000 ;
92115 int32_t var_b = var_a;
116+ std::cout << " Size and type of var_a: " << sizeof var_a << " , "
117+ << typeid (var_a).name () << std::endl;
118+ std::cout << " Size and type of obj_B: " << sizeof var_b << " , "
119+ << typeid (var_b).name () << std::endl;
93120
94- // 1.2 Implicit conversion through a specialised constructor
121+ // Implicit conversion through a specialised constructor
95122 A obj_A;
96123 B obj_B = obj_A;
97124
98- std::cout << " Size and type of obj_A: " << sizeof obj_A << " "
125+ std::cout << " Size and type of obj_A: " << sizeof obj_A << " , "
99126 << typeid (obj_A).name () << std::endl;
100- std::cout << " Size and type of obj_B: " << sizeof obj_B << " "
127+ std::cout << " Size and type of obj_B: " << sizeof obj_B << " , "
101128 << typeid (obj_B).name () << std::endl;
102129
130+ // -------------------------------------------------------------------------
103131 // 2. ===> EXPLICIT CONVERSION <===
104- std::cout << " 2. EXPLICIT CONVERSION:" << std::endl;
132+ // -------------------------------------------------------------------------
133+ std::cout << " ========================================================" << std::endl;
134+ std::cout << " ===> EXPLICIT CONVERSION <===" << std::endl;
135+ std::cout << " ========================================================" << std::endl;
105136
106- // 2.1 C-STYLE CASTS
107- std::cout << " 2.1 C-style cast:" << std::endl;
137+ // -------------------------------------------------------------------------
138+ // C-STYLE CASTS
139+ // -------------------------------------------------------------------------
140+ std::cout << sec_num++ << " . C-style cast:" << std::endl;
108141
109142 // 2.1.1 Cast between 16 and 32 bit integer types (good example)
110143 int32_t var_c = (int32_t )var_a;
@@ -119,32 +152,59 @@ int main() {
119152 << std::endl;
120153#endif
121154
155+ // -------------------------------------------------------------------------
122156 // 2.2 DYNAMIC_CAST<T>
123157 // Used for conversion of polymorphic types. Does runtime check of the types.
124158 // Returns nullptr if the conversion is not possible (so remember to check
125159 // the output!)
126- std::cout << " 2.2 dynamic_cast<T>:" << std::endl;
160+ // -------------------------------------------------------------------------
161+ std::cout << sec_num++ << " . dynamic_cast<T> (related classes):" << std::endl;
162+
163+ #ifdef COMPILATION_ERROR
164+ // Only polymorphic classes can be dynamic_cast'ed!
165+ C* p_obj_C2 = dynamic_cast <C*>(&obj_A);
166+ #endif
127167
128168 D obj_D;
129169 E obj_E;
130170 D* p_obj_D;
131171 E* p_obj_E;
132172
133- // 2.2.1 Cast derived to base ( fine)
173+ // 2.2.1 Cast derived to base - fine!
134174 p_obj_D = dynamic_cast <D*>(&obj_E);
135- if (p_obj_D = = nullptr ) {
136- std::cout << " Null pointer on 1st dynamic_cast " << std::endl;
175+ if (p_obj_D ! = nullptr ) {
176+ std::cout << " dynamic_cast of a derived class to its base is fine! " << std::endl;
137177 }
138178
139- // 2.2.2 Cast base to derived ( bad)
179+ // 2.2.2 Cast base to derived - bad!
140180 p_obj_E = dynamic_cast <E*>(&obj_D);
141181 if (p_obj_E == nullptr ) {
142- std::cout << " Null pointer on 2nd dynamic_cast " << std::endl;
182+ std::cout << " dynamic_cast of a base clase to one of its derived classes is bad! " << std::endl;
143183 }
144184
185+ std::cout << sec_num++ << " . dynamic_cast<T> (unrelated classes):" << std::endl;
186+ F *f1 = nullptr ;
187+ G *g1 = dynamic_cast <G*>(f1);
188+ if (!g1) {
189+ std::cerr << " Nice try - trying to dynamic_cast a nullptr yields a nullptr!\n " ;
190+ }
191+ F f2;
192+ G *g2 = dynamic_cast <G*>(&f2);
193+ if (!g2) {
194+ std::cerr << " Nice try - trying to dynamic_cast unrelated types yields a nullptr!\n " ;
195+ }
196+ try {
197+ F f3;
198+ G &g3 = dynamic_cast <G&>(f3);
199+ } catch (std::bad_cast &) {
200+ std::cerr << " Nice try - trying to dynamic_cast unrelated referneces throws a bad_cast exception!\n " ;
201+ }
202+
203+ // -------------------------------------------------------------------------
145204 // 2.3 STATIC_CAST<T>
205+ // -------------------------------------------------------------------------
146206 // Used for conversion of non-polymorphic types. Doesn't do runtime checks.
147- std::cout << " 2.3 static_cast<T>:" << std::endl;
207+ std::cout << sec_num++ << " . static_cast<T>:" << std::endl;
148208
149209 // 2.3.1 Cast between numeric types (good)
150210 double var_d = 3.14159265 ;
@@ -160,11 +220,13 @@ int main() {
160220 p_obj_E->print ();
161221#endif
162222
223+ // -------------------------------------------------------------------------
163224 // 2.4 REINTERPRET_CAST<T>
225+ // -------------------------------------------------------------------------
164226 // Allows any pointer to be converted into any other pointer type. Also allows
165227 // any integral type to be converted into any pointer type and vice versa. No
166228 // runtime checks are performed.
167- std::cout << " 2.4 reinterpret_cast<T>:" << std::endl;
229+ std::cout << sec_num++ << " . reinterpret_cast<T>:" << std::endl;
168230
169231 // 2.4.1 Cast one pointer type to another pointer type - bad, bad, bad!
170232 A* p_obj_A = &obj_A;
@@ -180,9 +242,11 @@ int main() {
180242 // Bad, bad, bad!
181243 p_obj_A = reinterpret_cast <A*>(var_j);
182244
245+ // -------------------------------------------------------------------------
183246 // 2.5 CONST_CAST<T>
247+ // -------------------------------------------------------------------------
184248 // Used to remove the const, volatile, and __unaligned attributes.
185- std::cout << " 2.5 const_cast<T>:" << std::endl;
249+ std::cout << sec_num++ << " . const_cast<T>:" << std::endl;
186250
187251 // 2.5.1 Modify a non-const variable through a reference-to-const (good
188252 // example)
@@ -200,4 +264,6 @@ int main() {
200264 const_cast <int32_t &>(rcl) = 4 ;
201265 std::cout << " The value of var_l: " << var_l << std::endl;
202266#endif
267+
268+ cppt::footer (argv[0 ]);
203269}
0 commit comments