Lesson of 21 July 2009 (afternoon)¶
Example of the use of class and inheritance
File inheritance.cc
1/*
2
3 Example of the use of class and inheritance
4
5*/
6
7// some include files
8
9#include <iostream>
10#include <string> // string support
11
12using namespace std ; // load standard namespace
13
14// standard alias for real numbers
15
16typedef double valueType ;
17
18/*
19 To activate debugging use
20
21 #define DEBUG
22
23 or in compilation use
24
25 g++ -DDEBUG ....
26*/
27
28#ifdef DEBUG
29 #define MSG_DEBUG(A) std::cout << A
30#else
31 #define MSG_DEBUG(A)
32#endif
33
34/*
35 Define the base class for geometric shape
36 */
37
38class shape {
39private:
40
41 std::string const theName ; // std::string STL class for string
42
43 // bouding box for the shape
44 valueType xmin, ymin, xmax, ymax ;
45
46 shape() ; // disable default constructor
47
48public:
49
50 shape( std::string const & n )
51 : theName(n)
52 {
53 MSG_DEBUG("shape(\"" << n << "\") constructor\n") ;
54 // default constructor
55 }
56
57 shape( std::string const & n,
58 valueType xm,
59 valueType ym,
60 valueType xM,
61 valueType yM )
62 // begin of the list of initializer calls
63 : theName(n) // call the constructor for the string theName
64 , xmin(xm) // call the consructor for xMin
65 , ymin(ym)
66 , xmax(xM)
67 , ymax(yM)
68 // end of the list of initializer calls
69 {
70 MSG_DEBUG("shape(\"" << n << "\",xMin,yMin,xMax,yMax) constructor\n") ;
71 }
72
73 ~shape() {
74 MSG_DEBUG("shape destructor\n") ;
75 } ; // destructor
76
77 std::string const & // return a constant reference to rthe string theName
78 name() const // method to access the private string theName
79 { return theName ; }
80
81 valueType const & xMin() const { return xmin ; }
82 valueType const & yMin() const { return ymin ; }
83 valueType const & xMax() const { return xmax ; }
84 valueType const & yMax() const { return ymax ; }
85
86} ;
87
88// operator for I/O
89std::ostream &
90operator << ( std::ostream & s, shape const & sp ) {
91 s << "CLASS = '" << sp . name() << "'\n"
92 << "bounding box = [ " << sp . xMin() << ", " << sp . yMin()
93 << ", " << sp . xMax() << ", " << sp . yMax() << " ] " ;
94}
95
96class quadrilateral : public shape { // define class quadrilateral inheriting by shape
97private:
98
99 quadrilateral() ; // block the default constructor
100
101public:
102
103 quadrilateral( std::string const & n,
104 valueType xm,
105 valueType ym,
106 valueType xM,
107 valueType yM )
108 : shape( n, xm, ym, xM, yM )
109 {
110 MSG_DEBUG("quadrilateral(\"" << n << "\",xMin,yMin,xMax,yMax) constructor\n") ;
111 }
112
113 valueType perimeter() const {
114 return 2*(xmax-xmin)+2*(ymax-ymin) ;
115 }
116} ;
117
118class square : public quadrilateral {
119private:
120
121 square() ; // block the default constructor
122
123public:
124
125 square( std::string const & n,
126 valueType xc,
127 valueType yc,
128 valueType len )
129 : quadrilateral( n, xc - len/2, yc - len/2, xc + len/2, yc + len/2 )
130 {
131 MSG_DEBUG("square(\"" << n << "\",xMin,yMin,xMax,yMax) constructor\n") ;
132 }
133
134} ;
135
136int
137main() {
138 shape s("a shape",-1,-1,2,3) ;
139 cout << s << "\n" ;
140 quadrilateral q("a quadrilateral", 1,-1,2,3) ;
141 cout << q << "\n" ;
142 square sq("a square", 1,1,20) ;
143 cout << sq << "\n" ;
144 return 0 ;
145}
Virtual methods
File inheritance2.cc
1/*
2
3 Example of the use of class and inheritance
4 with functions
5
6*/
7
8// some include files
9
10#include <iostream>
11#include <string> // string support
12
13using namespace std ; // load standard namespace
14
15// standard alias for real numbers
16
17typedef double valueType ;
18
19/*
20 To activate debugging use
21
22 #define DEBUG
23
24 or in compilation use
25
26 g++ -DDEBUG ....
27*/
28
29#ifdef DEBUG
30 #define MSG_DEBUG(A) std::cout << A
31#else
32 #define MSG_DEBUG(A)
33#endif
34
35/*
36 Define the base class for geometric shape
37
38 */
39
40class shape {
41private:
42
43 std::string const theName ; // std::string STL class for string
44
45 shape() ; // disable default constructor
46
47public:
48
49 shape( std::string const & n )
50 : theName(n)
51 {
52 MSG_DEBUG("shape(\"" << n << "\") constructor\n") ;
53 // default constructor
54 }
55
56 virtual ~shape() {
57 MSG_DEBUG("shape destructor\n") ;
58 } ; // destructor
59
60 std::string const & // return a constant reference to rthe string theName
61 name() const // method to access the private string theName
62 { return theName ; }
63
64 // define all the methods of the shape
65 // of type
66 virtual valueType xMin() const = 0 ; // make the class abstract
67 virtual valueType yMin() const = 0 ; // the methods are not defined in shape
68 virtual valueType xMax() const = 0 ; // but are defined in inherited classes
69 virtual valueType yMax() const = 0 ;
70 virtual valueType perimeter() const { return 0 ; } ; // = 0 ;
71 virtual void print( std::ostream & s ) const { s << "NONE" ; } ; // = 0 ;
72} ;
73
74// operator for I/O
75std::ostream &
76operator << ( std::ostream & s, shape const & sp ) {
77 sp . print( s ) ;
78 return s ;
79}
80
81class quadrilateral : public shape { // define class quadrilateral inheriting by shape
82private:
83
84 valueType xm, ym, xM, yM ;
85
86 quadrilateral() ; // block the default constructor
87
88public:
89
90 quadrilateral( std::string const & n,
91 valueType xm,
92 valueType ym,
93 valueType xM,
94 valueType yM )
95 : shape( n )
96 , xm(xm)
97 , ym(ym)
98 , xM(xM)
99 , yM(xM)
100 {
101 MSG_DEBUG("quadrilateral(\"" << n << "\",xMin,yMin,xMax,yMax) constructor\n") ;
102 }
103
104 valueType xMin() const { MSG_DEBUG("quadrilateral::xMin()\n") ; return xm ; }
105 valueType yMin() const { MSG_DEBUG("quadrilateral::yMin()\n") ; return ym ; }
106 valueType xMax() const { MSG_DEBUG("quadrilateral::xMax()\n") ; return xM ; }
107 valueType yMax() const { MSG_DEBUG("quadrilateral::yMax()\n") ; return yM ; }
108 valueType perimeter() const {
109 MSG_DEBUG("quadrilateral::perimeter()\n") ;
110 return 2*(xM-xm)+2*(yM-ym) ;
111 }
112 void print( std::ostream & s ) const {
113 MSG_DEBUG("quadrilateral::print(...)\n") ;
114 s << "quadrilateral CLASS = '" << name() << "'\n"
115 << "bounding box = [ " << xm << ", " << ym << ", " << xM << ", " << yM << " ] " ;
116 }
117} ;
118
119class square : public shape {
120private:
121
122 valueType xc, yc, len ;
123
124 square() ; // block the default constructor
125
126public:
127
128 square( std::string const & n,
129 valueType xc,
130 valueType yc,
131 valueType len )
132 : shape( n )
133 , xc(xc)
134 , yc(yc)
135 , len(len)
136 {
137 MSG_DEBUG("square(\"" << n << "\",xMin,yMin,xMax,yMax) constructor\n") ;
138 }
139
140 valueType xMin() const { MSG_DEBUG("quadrilateral::xMin()\n") ; return xc - len/2 ; }
141 valueType yMin() const { MSG_DEBUG("quadrilateral::yMin()\n") ; return yc - len/2 ; }
142 valueType xMax() const { MSG_DEBUG("quadrilateral::xMax()\n") ; return xc + len/2 ; }
143 valueType yMax() const { MSG_DEBUG("quadrilateral::yMax()\n") ; return yc + len/2 ; }
144 valueType perimeter() const {
145 MSG_DEBUG("quadrilateral::perimeter()\n") ;
146 return 4*len ;
147 }
148 void print( std::ostream & s ) const {
149 MSG_DEBUG("square::print(...)\n") ;
150 s << "square CLASS = '" << name() << "'\n"
151 << "center = [ " << xc << ", " << yc << "] edge legth = " << len ;
152 }
153
154} ;
155
156int
157main() {
158 //shape s("a shape") ;
159 //cout << s << "\n" ;
160 quadrilateral q("a quadrilateral", 1,-1,2,3) ;
161 square sq("a square", 1,1,20) ;
162
163 shape * v [] = { &q, &sq } ;
164
165 cout << *v[0] << "\n" ;
166 cout << *v[1] << "\n" ;
167
168 return 0 ;
169}
A class for solving a non linear system
File inheritance3.cc
1/*
2
3 Example of the use of class and inheritance
4 with functions for a class that solve a non linear system
5
6*/
7
8// some include files
9
10#include <iostream>
11#include <string> // string support
12#include <cmath> // for abs
13
14using namespace std ; // load standard namespace
15
16// standard alias for real numbers
17
18typedef double valueType ;
19typedef int indexType ;
20
21/*
22 To activate debugging use
23
24 #define DEBUG
25
26 or in compilation use
27
28 g++ -DDEBUG ....
29*/
30
31#ifdef DEBUG
32 #define MSG_DEBUG(A) std::cout << A
33#else
34 #define MSG_DEBUG(A)
35#endif
36
37void
38GaussJordan(valueType a[], valueType b[], indexType n) {
39 for ( indexType i=0 ; i < n ; ++i ) {
40 // pivoting parziale
41 indexType k=i ;
42 for ( indexType j=i+1 ; j < n ; ++j )
43 if ( abs(a[j+i*n]) > abs(a[k+i*n]) )
44 k = j ;
45 // swap row i with row k
46 if ( k != i ) {
47 std::swap( b[i], b[k] ) ;
48 for ( indexType j=i ; j < n ; ++j )
49 std::swap( a[i+j*n], a[k+j*n] ) ;
50 }
51 // divide row i by a(i,i)
52 valueType bf = a[i+i*n] ;
53 b[i] /= bf ;
54 for ( indexType k=i+1 ; k < n ; ++k )
55 a[i+k*n] /= bf ;
56
57 // eliminazione
58 for ( indexType j=0 ; j < n ; ++j ) {
59 if ( j==i) continue ; // skip row i
60 valueType bf = a[j+i*n] ;
61 b[j] -= bf * b[i] ;
62 for ( indexType k=i+1 ; k < n ; ++k )
63 a[j+k*n] -= bf * a[i+k*n] ;
64 }
65 }
66}
67
68// an abstract class that store the interface for the non linear system
69class nonlinear {
70private:
71
72 std::string const theName ; // std::string STL class for string
73
74 nonlinear() ; // disable default constructor
75
76 valueType epsi ;
77 valueType * basePointer ;
78 valueType * Xk ;
79 valueType * Xkp1 ;
80 valueType * Fk ;
81 valueType * Jk ;
82
83 void
84 allocate( indexType neq ) {
85 indexType n = 3*neq + neq*neq ; // total number of float to allocate
86 basePointer = new valueType[n] ;
87 Xk = basePointer ;
88 Xkp1 = Xk + neq ;
89 Fk = Xkp1 + neq ;
90 Jk = Fk + neq ;
91 }
92
93 void
94 release() {
95 delete [] basePointer ;
96 }
97
98public:
99
100 nonlinear( std::string const & n )
101 : theName(n)
102 , epsi(1e-8)
103 {
104 MSG_DEBUG("nonlinear(\"" << n << "\") constructor\n") ;
105 // default constructor
106 }
107
108 virtual ~nonlinear() {
109 MSG_DEBUG("nonlinear destructor\n") ;
110 } ; // destructor
111
112 std::string const & // return a constant reference to rthe string theName
113 name() const // method to access the private string theName
114 { return theName ; }
115
116 // algorthm to find the solution
117 bool solve( valueType x[] ) ;
118
119 // interface for the nonlinear system
120 virtual indexType numEquation() const = 0 ;
121 virtual void functionEval( valueType const x[], valueType f[] ) = 0 ;
122 virtual void jacobianEval( valueType const x[], valueType J[] ) = 0 ;
123 virtual void guess( valueType x[] ) const = 0 ;
124
125} ;
126
127bool
128nonlinear::solve( valueType x[] ) {
129 valueType err ;
130 indexType neq = numEquation() ;
131 // newton method
132 allocate( numEquation() ) ;
133
134 // initialize by guess
135 guess( Xk ) ;
136
137 for ( indexType k = 0 ; k < 100 ; ++k ) {
138 functionEval( Xk, Fk ) ;
139 jacobianEval( Xk, Jk ) ;
140
141 // compute J^(-1)*Fk by solving J*x = Fk and store the result in Fk
142 GaussJordan(Jk, Fk, neq ) ;
143
144 // Xk1 = Xk - J^(-1)*Fk
145 for ( indexType i = 0 ; i < neq ; ++i )
146 Xkp1[i] = Xk[i] - Fk[i]/2 ;
147
148 // check termination
149 err = 0 ;
150 for ( indexType i = 0 ; i < neq ; ++i )
151 err = max( err, abs( Xkp1[i]-Xk[i] ) ) ;
152 if ( err < epsi ) break ;
153
154 // Xk = Xkp1 ;
155 std::copy( Xkp1, Xkp1 + neq, Xk ) ;
156 }
157
158 // copy solution to x
159 std::copy( Xk, Xk + neq, x ) ;
160
161 release() ;
162 return err < epsi ;
163}
164
165
166// Using the class to solve the problem
167//
168// 10 x^2 + x^2 + y = 1
169// x + 10 y^2 - y^2 = 2
170//
171
172class my_problem : public nonlinear {
173
174
175public:
176
177 my_problem() : nonlinear( "my problem" )
178 { }
179
180 virtual indexType numEquation() const { return 2 ; }
181
182 virtual void functionEval( valueType const X[], valueType F[] ) {
183 valueType const & x = X[0] ; // make alias for X[0] and X[1]
184 valueType const & y = X[1] ;
185 F[0] = 10*x + x*x + y - 1 ;
186 F[1] = x + 10*y - y*y - 2 ;
187 }
188
189 // 10+2*x 1
190 // 1 10-2*y
191 virtual void jacobianEval( valueType const X[], valueType J[] ) {
192 valueType const & x = X[0] ; // make alias for X[0] and X[1]
193 valueType const & y = X[1] ;
194 // store the matrix by column
195 J[0] /* J(0,0) */ = 10+2*x ;
196 J[1] /* J(1,0) */ = 1 ;
197 J[2] /* J(0,1) */ = 1 ;
198 J[3] /* J(1,1) */ = 10-2*y ;
199 }
200
201 virtual void guess( valueType X[] ) const {
202 valueType & x = X[0] ; // make alias for X[0] and X[1]
203 valueType & y = X[1] ;
204 x = y = 0 ;
205 }
206
207} ;
208
209int
210main() {
211
212 my_problem p ;
213
214 valueType x[2] ;
215 bool ok = p . solve( x ) ; // call iterative method to solve non linear problem
216 if ( ok ) cout << "problem solved\n" ;
217 else cout << "problem NOT solved\n" ;
218
219 cout << "x = " << x[0] << " y = " << x[1] << '\n' ;
220
221 return 0 ;
222}