300 likes | 568 Views
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
E N D
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);booloperator==(const typeinfo&) const;booloperator!=(const typeinfo&) const; bool before(const typeinfo&) const; const char *name(void) const;private: typeinfo(const typeinfo&); typeinfo& operator= (const typeinfo&); //.. Implementation dependent fields}; 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} No RTTI in early versions of the language.
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
Ellipse draw+ hide+ rotate+ Circle rotate++ centre+ Implementation of Virtual Functions E1 • class Ellipse { • // ... • public: • virtualvoid draw() const; • virtualvoid hide() const; • virtualvoid rotate(int); • } E1, E2, *P; E2 P • class Circle: public Ellipse { • //... • public: • virtual void rotate(int); • virtual Point centre(); • } C1, C2, C3; C1 C2 C3
E1 E2 C1 C2 C3 Ellipse VMT Circle VMT draw hide rotate draw hide rotate centre The Virtual Methods Table (vtbl) P Ellipse :: draw Circle :: centre Ellipse :: hide Ellipse :: rotate Circle :: rotate
E1 E2 C1 C2 C3 Ellipse VMT Circle VMT draw hide rotate draw hide rotate centre P->rotate() P Ellipse :: draw Ellipse :: hide Circle :: centre Ellipse :: rotate Circle :: rotate
Object Oriented ProgramminginC++ 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; } int max (int , int); // explicit void fn (int i, char c) { max (i , i); // ok max (c, c); // ok max (i, c); // ok } 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 }
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
top ... ... ... ... bottom Example: A Generic Stack • 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> bool Stack<T> :: push(const T& x) { if (full()) return false; *top++ = x; return true; } template <class T> Stack<T> :: Stack(int sz) { size = sz; top = bottom = new T [sz]; } 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 << ‘ ‘; } ...