Object Oriented Programming in C++

Download Report

Transcript Object Oriented Programming in C++

Run Time Type Identification
(RTTI)


Always exists in OOP: a prerequisite for
dynamic binding
Accessible to programmer? (this is what one
usually means by RTTI)
• Not necessarily in static type systems
• Almost everything can be done without it!
• Almost always in dynamic type systems
• Without it, it is impossible to be sure that
an object will recognize a message!
class typeinfo {
public:
virtual ~typeinfo(void);
bool operator==(const typeinfo&) const;
bool operator!=(const typeinfo&) const;
bool before(const typeinfo&) const;
const char *name(void) const;
private:
typeinfo(const typeinfo&);
typeinfo& operator= (const typeinfo&);
//.. Implementation dependent fields
};
No RTTI in early versions
of the language.
class Base {
...
};
void f(Base *p)
{
const typeinfo& a = typeid(p);
// Type information for Base *
const typeinfo& a = typeid(*p);
// Actual run time type of *p
}
RTTI Example
#include <iostream.h>
#include <typeinfo.h>
class Base {
public:
Base():hide(0){}
void mutate(int i){ hide = i;}
virtual void print()const
{cout <<
"hide in Base = " << hide << endl;}
private:
int hide;
};
class One: public Base {
public:
One():Base(),data(0) {}
void mutate(int i){ data = i;}
void print()const {cout <<
"data in One = "<< data << endl;}
void newfunc() {cout << "Hi\n";}
private:
int data;
};
RTTI Example
int main ()
{
Base* bptr; One* derived; One o1; bptr = &o1;
derived = dynamic_cast<One*>(bptr);
derived->print();derived->newfunc();
cout << typeid(bptr).name() << endl << typeid(*bptr).name() << endl;
if (typeid(*bptr) == typeid(One))
cout << "type bprt & derived same" << endl;
cout << typeid(bptr).name();
cout << " before " << typeid(o1).name() << ": " <<
(typeid(bptr).before(typeid(o1)) ? true : false) << endl;
}
More about casting operators
class Car {
};
class SpecialCar : public Car {
};
void fun (SpecialCar *psc);
main()
{
const SpecialCar sc;
update (&sc) ; // error
update (const_cast<SpecialCar*>(&sc)) ; // fine! - C style : (SpecialCar*)&sc
Car *pc = new SpecialCar;
update(const_cast<SpecialCar*>(pc)); // error ! This not the const_cast purpose !
update(dynamic_cast<SpecialCar*>(pc)); // OK if pc is really points
// to this one
Implementation of Virtual
Functions
class Ellipse {
// ...
public:
virtual void draw() const;
virtual void hide() const;
virtual void rotate(int);
} E1, E2, *P;
class Circle: public Ellipse {
//...
public:
virtual void rotate(int);
virtual Point centre();
} C1, C2, C3;
E1
Ellipse
draw+
hide+
rotate+
E2
P
Circle
C1
rotate++
centre+
C2
C3
The Virtual Methods Table (vtbl)
P
E1
E2
Ellipse VMT
draw hide rotate
C1
C2
C3
Circle VMT
draw hide rotate centre
Ellipse :: draw
Ellipse :: rotate
Ellipse :: hide
Circle :: centre
Circle :: rotate
P->rotate()
P
E1
E2
Ellipse VMT
draw hide rotate
C1
C2
C3
Circle VMT
draw hide rotate centre
Ellipse :: draw
Ellipse :: rotate
Ellipse :: hide
Circle :: centre
Circle :: rotate
Object Oriented Programming
in
C++
Chapter 8
Templates
Introduction

Getting Reuse Through Templates
• Inheritance sometimes isn’t enough nor is it
appropriate

What are Templates
• An attempt on Generic code
• Parameterized Types
Function Templates
Consider
int max (int x, int y)
{ return (x > y) ? x : y;}

If we want to compare many types with max(),
then many overloaded versions are needed or
...
We might use polymorphism or ...
We might use macros
#define max (x,y) (( x > y) ? x : y)
Function Template example
template <class T>
T max (T x, T y)
{
return (x > y) ? x : y;
}
...
Myclass a,b;
max(7,8);
max (a,b);
Overloaded Function Template
Function templates can be overloaded.
char *max (char *st1, char *st2)
{
return strcmp(st1, st2) > 0 ? x: y;
}
 Declared explicitly here, this function will
be called if the arguments are of type
char*.
Overloaded Function Templates
template <class T>
T max (T x, T y)
{
return (x > y) ? x : y;
}
void fn (int i, char c)
{
max (i , i);
// ok
max (c, c); // ok
max (i, c); // illegal
}
template <class T>
T max (T x, T y)
{
return (x > y) ? x : y;
}
int max (int , int);
// explicit
void fn (int i, char c)
{
max (i , i);
// ok
max (c, c);
// ok
max (i, c);
// ok
}
Another example
template <class T>
T max( T a[], int size)
{
int index = 0;
for(int i=1; i<size; ++i)
if( a[i] > a[index] ) index = i;
return a[index];
}
Using max with Rational class
template<class T> T max( T a[], int size);
main()
{
Rational v[20];
...
Rational mr = max(v, 20); // Problem ?
cout << “The max: “ << mr << ‘\n’;
...
}
Pre conditions
bool Rational :: operator>(const Rational& r)
{
if (num*r.den > r.num*den)
return true;
else
return false;
}
ostream& operator<<(ostream& os, const Rational& r)
{
os << r.num << ‘/’ << r.den;
return os ;
}
(declared as a friend function in class rational)
Template Classes

Many classes are relatively insensitive to the data
type of their members

Container classes carry out similar operations to
• add
• remove
• find

The operations are the same whatever the type of
the data members
Example:
A Generic Stack
top
bottom
...
...
...
...
Operations:
•pop
•push
•empty
•full
•initialize
•destroy
A Stack of Integers
class Stack {
int* top, bottom;
int size;
public:
Stack(int);
bool push(int);
bool pop(int&);
bool empty();
bool full();
~Stack();
};
A Class Template
template <class T> class Stack {
T *top, *bottom;
int size;
public:
Stack(int);
bool push(const T&);
bool pop(T&);
bool empty();
bool full();
~Stack():
};
Class implementations
template <class T>
Stack<T> :: Stack(int sz)
{
size = sz;
top = bottom = new T [sz];
}
template <class T>
bool Stack<T> :: push(const T& x)
{
if (full()) return false;
*top++ = x;
return true;
template <class T>
bool Stack<T> :: empty()
{
if (top == bottom)
return true;
return false;
}
}
template <class T>
bool Stack<T> :: pop(T& x)
{
if (empty()) return false;
x = *--top;
retrun true;
}
Cont.
template <class T>
Stack<T> :: ~Stack()
{
delete [] bottom;
}
template <class T>
bool Stack<T> :: full()
{
if (top-bottom >= size)
return true;
return false;
}
Using Stack Template
main()
{
Stack<int> si(100);
Stack<char> sc(20);
Stack<float> sf(25);
Stack<Rational> sr(50);
Stack<Employee> se(90);
...
...
int i = 0;
while (!si.full())
si.push(i++);
int a;
while(!si.empty()) {
s1.pop(a);
cout << a << ‘ ‘;
}
...