210 likes | 312 Views
Types, Structs, Classes, Objects. CS101 2012.1. Creating our own types. Thus far, we have used primitive types (bool, int, float, long, double, etc.) pair<T1, T2> native arrays, vector<T>, matrix<T> collections map<K,V>, multimap<K,V> Why do we need our own type definitions?
E N D
Types, Structs, Classes, Objects CS101 2012.1
Creating our own types • Thus far, we have used • primitive types (bool, int, float, long, double, etc.) • pair<T1, T2> • native arrays, vector<T>, matrix<T> • collections map<K,V>, multimap<K,V> • Why do we need our own type definitions? • More readable type names • Shorter type names • Pack diverse fields into one record (arrays store only one type; maps, two) Chakrabarti
typedef • “Comfort feature” • Shorthand for types (n.) that are too long to type (v.) again and again • typedef pair<string, int> WordCount; • Makes types more readable • typedef int Ticket; • typedef double Time; • Convention is to define our type names and class names starting with UpperCase • Variables start with lowerCase Chakrabarti
Struct • Fields in a record: for each student • Roll number (unique key) • Name • Date of birth … • For each customer • Ticket number • Arrival, service begin, departure times • Instead of separate collections with each field, use one collection of records, each record with fields Chakrabarti
Simple starting examples struct Point { double x, y; }; struct Circle { Point center; double radius; }; Member or fieldname Member or fieldtype Types you defined can be used thereafter in other types Chakrabarti
Member initialization and access • Three styles of initialization • Fill in all fields by name, separately • As expressionCircle{ {.6, .8}, 2 } • As declarationCircle circ { {.6, .8}, 2 }; • circ.radius, circ.center.x, etc. • On both lhs and rhs • Passing as parameters to functions • Default is pass-by-value: copy everything • Can also pass by reference Chakrabarti
Class = Struct + ? • Constructor(s) • How to set up the initial configuration • Perhaps allocate memory • Destructors • Release resources and clean up state • Methods • Change the state of the struct members in clean, controlled ways • Access control: public, protected, private • Inheritance (extending classes) Chakrabarti
Point constructor and destructor struct Point { double x, y; Point(double _x, double _y) { x = _x, y = _y; cout << "Point " << endl; } ~Point() { cout << "~Point " << endl; } }; Why do we need explicit constructors and destructors if we already have initializers? Chakrabarti
Constructors • Suppose we need the area of a circle oftenstruct Circle { Point center; double radius, area; } • But we don’t want every declaration of a circle variable to compute the area • Let a circle compute its own area when it is initialized • (What happens when radius changes?) Chakrabarti
Example constructor struct Circle { Point center; double radius, area; Circle(double cx, double cy, double rad) { center.x = cx, center.y = cy; radius = rad; area = pi * rad * rad; } }; Chakrabarti
this • Special variable representing (address of) current object, available inside constructor, destructor, and methods Point(double _x, double _y) { cout << "Point@" << this << "(" << _x << "," << _y << ")\n"; } • Fields can also be written as this->x and this->y Chakrabarti
Initializing constant fields struct Point { const double x, y; Point(double _x, double _y) : x(_x), y(_y) { /* nothing */ } } • Can never change x or y after a Point is constructed • But can you assign a whole Point variable? (let’s try and see) Chakrabarti
The copy constructor • What happens when we sayPoint pt2 = pt1; • The “copy constructor” is invoked to construct a new Point pt2 out of pt1 Point(const Point& other) : x(other.x), y(other.y) { cout << "Point@" << this << " copied from " << &other << endl; } Chakrabarti
Memory management • When exactly are constructors and destructors called? • Consider this code: Point pt1(3,4), pt2(5,5); vector<Point> points; points.push_back(pt1); points.push_back(pt2); cout << "exiting main\n"; Chakrabarti
Explanation Point@0xbfa1e320(3,4) Point@0xbfa1e310(5,5) Point@0x963b008(3,4) copied from Point&0xbfa1e320(3,4) Point@0x963b030(5,5) copied from Point&0xbfa1e310(5,5) Point@0x963b020(3,4) copied from Point&0x963b008(3,4) ~Point@0x963b008(3,4) exiting main ~Point@0x963b020(3,4) ~Point@0x963b030(5,5) ~Point@0xbfa1e310(5,5) ~Point@0xbfa1e320(3,4) Allocated on stack Native array in heapis getting extended; firstelement is copied over Freed from stack Chakrabarti
A first method • (For mutable, not constant Points) void move(double dx, double dy) { x += dx, y += dy; } void print() { cout << x << ' ' << y << ' '; } void load() { cin >> x >> y; } Chakrabarti
Members and methods • Methods are like functions except they have access to the invisible variable this • You don’t have to say this->x all the time, if x is not otherwise defined in scope, x means this->x • What goes for members also goes for methods: can access this->meth(arg) as meth(arg) • meth(arg) and other.meth(arg) or otherp->meth(arg) are different • Same method invoked on different instances Chakrabarti
Inheritance struct Point { double x, y; }; struct ColoredPoint : public Point { Color color; } Struct ColoredPointMass : public ColoredPoint { double mass; } Chakrabarti
A vector that writes and reads itself • Boost lets you read and write matrices, but these are in textual format • An integer that is 4 bytes in RAM may take up to 11 bytes to store in decimal • We would like to store in integer in 4 bytes in a disk file too • But we cannot directly view this file because it does not have ASCII character codes in it • To store a vector<int> to disk, we store • The size in 4 bytes • Each element in 4 bytes Chakrabarti
Inherited class class SerializableVector : public vector<int> { public: // store myself to named file void store(const char *fname); // load myself from named file void load(const char *fname); }; Base class fields and methods remain available Chakrabarti
Warning: serializing pointer data • Much harder game • Pointer value is ephemeral, can change with next invocation of code • Want to save logical structure of queue or tree etc. to disk, not actual pointers • Generally means traversing whole data structure systematically, giving logical IDs to each record • How about circular queues or other data structures with pointer cycles? Need to mark Chakrabarti