-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcpp_cheatsheet1.cpp
179 lines (137 loc) · 5.1 KB
/
cpp_cheatsheet1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/* written by Nick Shin - [email protected]
* the code found in this file is licensed under:
* - Unlicense - http://unlicense.org/
*
* this file is from https://github.com/nickshin/CheatSheets/
*
*
* this code will show the basic principles of:
* - constructors
* - destructors
* - base, derived, multiple inheritance and friendship classes
* - private vs protected vs public member data access
* - pure and basic virtual function declarations
* - polymorphism
* - type casting
*
*
* to compile:
* g++ cpp_cheatsheet1.cpp -o cpp_cheatsheet1
*
* to run:
* ./cpp_cheatsheet1
*
*
* best viewed in editor with tab stops set to 4
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*/
#include <iostream> // cout
using namespace std;
// constructors and destructors will print the order
// base and derived classes are built and torn down
class Derived; // forward declaration
class Abstract
{
private:
int a_number; // normally not accessible in derived class
public:
Abstract() { cout << "abs: no params\n"; }
Abstract( int num ) { cout << "abs: int params\n"; a_number = num; }
~Abstract() { cout << "abs: bye bye\n"; }
virtual int please_define_me( void ) = 0; // pure virtual function
// polymorphism example
// as well as multiple inheritance issue: see main() for details
int get_num( void ) { return this->please_define_me(); }
friend class Derived; // allowing access to private members
friend class Poly; // allowing access to private members
};
class Base
{
private:
// int b_number; // can not be accessed in derived class
protected:
int b_number; // can be accessed in derived class
public:
Base() { cout << "base: no params\n"; }
Base( int num ) { cout << "base: int params\n"; b_number = num; }
~Base() { cout << "base: bye bye\n"; }
virtual int get_num( void ) { return 0; } // basic virtual function
void set_num( int num ) { b_number = num; }
};
class CantCompile // testing multiple inheritance ambiguity
{
private:
int x;
public:
void set_num( int num ) { x = num; } // compiler will complain about this if used in Derived class below
};
class Derived: public Abstract, public Base//, public CantCompile
{
public:
// XXX: watch how different class creation are done,
// XXX: try out the two different Derived(int) constructors
Derived() { cout << "derived: no param\n"; }
Derived( int num ) : Abstract( num ) { cout << "derived: int param\n"; }
// Derived( int num ) : Base( num ) { cout << "derived: int param\n"; }
~Derived() { cout << "derived: bye bye\n"; }
// friend: note how please_define_me() is accessing a private base class member
int please_define_me( void ) { return a_number; };
// also, note how b_number is declared protected, or else this will not compile
int get_num( void ) { return b_number; }
};
class Poly: public Abstract
{
public:
// the following two are same
// Poly( int num ) { a_number = num; }
Poly( int num ) : Abstract( num ) { }
int please_define_me( void ) { return a_number * 2; }
};
int
main()
{
cout << "*** dd1 constructor sequence:\n";
Derived dd1;
dd1.set_num( 1234 );
cout << "dd1 num: " << dd1.get_num() << endl;
cout << "\n*** dd2 constructor sequence:\n";
// multiple inheritance issue:
// if Derived was compiled with [ Derived( int num ) : Abstract( num ) ]
// get_num() will not return the expected value of 5678
// else if Derived was compiled with [ Derived( int num ) : Base( num ) ]
// abstract numbers are unknown...
Derived dd2( 5687 );
cout << "dd2 num: " << dd2.get_num() << endl;
cout << "dd2 abstract num: " << dd2.Abstract::get_num() << endl;
cout << "dd2 abstract num again: " << dd2.please_define_me() << endl;
// polymorphism
cout << "\n*** polymorphism:\n";
Abstract *pp1 = &dd2;
Abstract *pp2 = new (nothrow) Poly( 10 );
cout << "pp1 num: " << pp1->get_num() << endl;
if ( pp2 ) cout << "pp2 num: " << pp2->get_num() << endl;
// casting
cout << "\n*** casting:\n";
CantCompile cc;
pp1 = (Abstract*)&cc; // explicit conversion -- see reinterpret_cast below
// cout << pp1->get_num() << endl; // will crash or produce unexpected results
try {
Base* pbd = new Derived;
Base* pbb = new Base;
Derived* pd;
pd = dynamic_cast<Derived*>(pbd); // ok: derived-to-base
if ( ! pd ) cout << "Null pointer on first type-cast\n";
pd = dynamic_cast<Derived*>(pbb); // wrong: base-to-derived
if ( ! pd ) cout << "Null pointer on second type-cast\n";
pd = static_cast<Derived*>(pbb);
if ( ! pd ) cout << "Null pointer on third type-cast\n";
// else cout << "pd num: " << pd->get_num() << endl; // will crash or produce unexpected results
// pd = static_cast<Derived*>(&cc); // will not compile
pd = reinterpret_cast<Derived*>(&cc); // will compile and is just like explicit conversion above
if ( ! pd ) cout << "Null pointer on fourth type-cast\n";
// else cout << "pd num: " << pd->get_num() << endl; // will crash or produce unexpected results
} catch( exception& e ) { cout << "Exception: " << e.what(); }
// note the desctructor sequences here...
cout << "\n*** destructor sequences:\n";
return 0;
}