26
. Plab – Tirgul 11 RTTI, Binary files

Plab – Tirgul 11 RTTI, Binary files. RTTI – why? Problem: u Up-casting works fine. Treating sub-class as base class Shape * s = new Circle(); u What

  • View
    220

  • Download
    1

Embed Size (px)

Citation preview

.

Plab – Tirgul 11RTTI,

Binary files

RTTI – why?

Problem: Up-casting works fine.

Treating sub-class as base classShape * s = new Circle();

What about down-casting? might not be safe ! correctness cannot be determined

by the compiler.Circle * c = (Circle*) s;

Shape

Line Circle

RTTI

RTTI – Run Time Type Information

Mechanisms for RTTI:

1. dynamic_cast operator

2. typeid operator (and type_info class)

The ‘dynamic_cast‘ operator

dynamic_cast<T>(expression)

Enables run-time type checking: returns a valid pointer if “expression” is

of type “T” NULL otherwise

Cast of a reference type throws an exception when it fails (“bad_cast”)

Dynamic_cast : example

Shape* s = container.pop();

Circle* c = dynamic_cast<Circle*>(s);

if ( c != NULL ) { // c is a circle

c->doSomething();

else

handle(); //handle unexpected event

Note: the actual type of “s” is not mentioned! Can be any sub-class of Circle.

Dynamic_cast : example

Shape s; Circle c;

Line l; ThinLine tl;

Shape* arr[4] = {&s, &c, &l, &tl};

for ( int i=0; i<3; i++ ) {

Line * pl = dynamic_cast<Line*>( arr[i] );

pc == NULL? cout << “cast ok\n” :

cout << “cast fail\n”;

}

Shape

LineCircle

Output:

cast fail // Shape to Line

cast fail // Circle to Line

cast ok // Line to Line

cast ok // ThickLine to Line

ThickLine

dynamic_cast - more

dynamic_cast<T>(expression)

Note: Used only on pointer or reference types. Can be used for up-cast, down-cast

and also for cross-cast (out of this scope) Only for types with virtual-functions

(“Polymorphic types”) These object have a space for the information

about the type: the virtual function table

dyn_cast: only for polymorphics

void foo(Shape * s, Time * t) {

Circle * c = dynamic_cast<Circle*>( s ); //ok

Date * date = dynamic_cast<Date*>( t ); //error

}

class Circle : public Shape {virtual void draw();…

}

class Date : public Time {… // Time has no virtual functions

}

RTTI : typeid operator• Obtains info about an object/expression

• usage: typeid( obj ) (like “sizeof”)

Example:

Dog d;Cat c;cout << “d is a “ << typeid(d).name() << “,”

<< “c is a “ << typeid(c).name() <<endl;

Output: d is a Dog, c is a Cat

type_info class• typeid(expression) returns an object of the type_info class.

• e.g. type_info& ti = typeid(d);class type_info {

public:

bool operator==( type_info const&)const;

char const* name() const;

private:

type_info( type_info const&); //prevent copying

type_info& operator=( type_info const& );

}

RTTI misusevoid rotate( shape const& s ) {

if (typeid(s) == typeid(Circle) )

//do nothing

else if (typeid(s) == typeid(Triangle) )

//rotate Triangle

else if (typeid(s) == typeid(Rectangle) )

//rotate Rectangle

}

• Use virtual functions (i.e. polymorphism) when you can !•VERY common misuse of RTTI

.

Binary files

Leading example: image files

Images are stored as matrices of numbers (Pixels).

Here, we deal with gray-scale images (“black and white”)

8 bits per pixel i.e. each pixel between 0 and 255

0 is white, 255 is black, others are gray

255

0

0

255

0

100

storing images

How can we store images on files? For each image we want to store:

width //integer height //integer number of bits per pixel //short the pixels //matrix of integers

Requirements: read/write easily, save space, save computation, etc.

storing imagesFirst try: text files (like you did so far)

width = 3

height = 2

bits_per_pixel = 8

255, 0, 0

0, 255, 100

“myImg.txt”

cons: long needs parsing (e.g.

atoi for numbers)

pros: readable by humans

easy to edit but who handles

images like that?

Binary filesBetter solution: Binary files

Save the data the way the computer holds it

pros: Smaller No parsing (faster)

Widely used ! For example: BMP files, other data

cons: hard to read for

humans Machine

dependant

Images as binary files

3

2

8 255

0 0

0 255

100

width2 bytes[0,…,0,0,1,1]

height2 bytes[0,…,0,0,1,0]

Images as binary files

3

2

8 255

0 0

0 255

100

bits per pixel1 byte[0,0,0,0,1,0,0,0]

Images as binary files

3

2

8 255

0 0

0 255

100

pixel1 byte[1,1,1,1,1,1,1,1]

pixel1 byte[0,0,0,0,0,0,0,0]

Binary files

3

2

16

255

0

0

255

0

0

bits per pixelnow value 16

Example: writing a binary filePixel pixs[30];  

int width = 100, height = 150;

short bitsPerPix = 16;binary

open for writing

ofstream outfile;  

outfile.open(“pic.raw", ios::bin | ios::out);

outfile.write(&width, sizeof(int));

outfile.write(&height, sizeof(int));

outfile.write(&bitsPerPix, sizeof(short));

outfile.write(pixs, 30*sizeof(Pixel));  

outfile.close();

ostream& write( char const* str, streamsize n);

.

Learn by yourselves:c++ casting

(see slides ahead andStroustrup 15.4 and more)

c++ style casting

At the beginning c++ supported two styles of casts: (typename)expression typename(expression)

Instead there are now four new casting operators: static_cast<type>(expression) const_cast<type>(expression) reinterpret_cast<type>(expression) dynamic_cast<type>(expression)

The 'static_cast'operator

Works where implicit conversion exists standard or user-defined conversion up-casts

Safer that “old-style” casts e.g. won’t cast int* to float*

Failure causes a compiler error No dynamic checking is done!

int i = static_cast<int>(12.45);

static_cast<type>(expression)

The ‘const_cast'operator

Is used to remove (or add) const-ness:void g(C * cp);

void f(C const* cp) {g(const_cast<C *>(cp));

} Usually, you should design your

variables/methods such that you won’t have to use const_cast.

Failure causes compiler errors

const_cast<type>(expression)

‘reinterpret_cast'operator

Is used to reinterpret byte patterns.

double d(10.2);

char* dBytes =

reinterpret_cast<char *>(&d); Circumvents the type checking of c++. Very implementation-dependent. Rarely used.! Very dangerous !

reinterpret_cast<type>(expression)