CS60 Lecture 19 --------------- Announce ------------- - hw13 due - proj4 due fri Today ------------- - review basic inheritance - advanced inheritance - virtual functions - event driven prog Review Basic Inheritance ------------------------ - reason we have classes/OO is to foster code reuse and clean abstractions - inheritance moves more towards clean abstractions - We often have objects that have many data/functionality in common - use inheritance to set up herarchy of objects - child classes can 'redefine' data/functions inherited from parent - Ex: vehicles - Ex: figures figure | \ circle rectangle - already have seen some issues that arise - constructors/destructors/= op cannot be inherited Virtual Functions ------------------ - each child class has it's own 'draw' function since it is different for each child class - figure has a 'center' function that moves center point to middle of screen and then draws the figure class figure { private: int x, y; public: ... void center() {x=128; y=128; draw()}; }; - PROBLEM: figure has 'center' function that uses 'draw', but figure doesn't HAVE a draw function! - have to implement a draw() func for 'figure' - now, compiler is happy compiling the figure::center function, since we've defined a 'draw' function void draw() {cout << "drawing a figure" << endl;}; - PROBLEM: if we have circle instance, that uses 'a.center()', we'll get the figure draw() implementation! - C++ gives us 'virtual functions' - allow us to define a function before it's implemented - use 'virtual' keyword before function in 'figure' definition class figure { private: int x, y; public: ... void center() {x=128; y=128; draw()}; virtual void draw() {cout << "drawing figure" << endl;}; }; class circle : public figure { public: void draw() { cout << "drawing circle" << endl;}; }; - circle implements it's own unique 'draw' function - virtual functions give us the ability to use 'late binding' which means attaching code to a function name at runtime. - at runtime, when we make an instance of 'circle' and call 'center', the figure::center code will run and when it gets to 'draw()' will use circle's draw(), since the function was declared virtual - 'polymorphism' means 'function name that has multiple implementations', in C++ case, virtual functions allow us to have 'polymorphism' in the language Pure Virtual Functions ----------------------- - note how we had to define a draw function on 'figure' even though it is never used, this is a waste of time/memory. - in fact, we never plan on ever using a 'figure' instance, only plan to use child classes - C++ allows us to specify 'pur virtual' functions, in figure virtual void draw()=0; - now compiler doesn't need an implementation of 'draw' for 'figure' - cannot have an instance of classes that have pure virtual functions, get compiler error - other OO languages (java) ALL functions are pure virtual by default! Related Type Conversion -------------------------- - we have a vehicle and a motorcycle vehicle a; motorcycle k; - C++ does not allow us to make assignments from larger objects to smaller objects k = a; // illegal - other way IS allowed a = k; - seems counter intuitive - reason is that 'k' has more variables than a, and no way to initialize from just knowledge of 'a' data - data that is in 'k' but not 'a' is lost. - but only if variables are on the stack!!! - if we're using pointers, type of parent class can 'change' vehicle *a; motorcycle *k; k = new motorcycle; a = k; - a can now be treated as a motorcycle OR a vehicle. if both define function 'foo', will get vehicles version of 'foo' (foo redefined). if a function is tagged virtual, a will get 'motorcycle's version Event Driven Programming ------------------------- - many programming models. - so far we have been using the most common, start in main, walk through functions, exit - we've also used a 'main loop' model where we do some initialization, then enter a main loop which repeats until some event happens, then we quit - extension of this idea is the event driven model - do some initialization - enter an 'event loop' - event loop runs forever, detects 'events', if no events has default (idle) function - upon recving an event, call function associated with the event (callback) ** Draw Pic - what does this remind us of? - AN OS!!! - usually, event loop systems are prewritten, we need only code the functions that get called upon event reciept - graphical systems are almost always event driven - GUI, games, 3d graphics, animations - also OS and network servers - ex: glut - do some init - set up window - set up graphical context - register callbacks - assign functions to events (by passing function names) - enter main glut event loop, which detects - keyboard events - mouse events - window events (enter, exit, focus) - draw events (calls one by default, then program has to send another) - idle event (no events, can register idle function) - since we are not in main, and we do not have access to the event loop, all of our own code lives in callback routines. - problem is maintaining state since we're always in subfunctions that leave scope. have no way to pass variables from main. - all stateful variables must be global - video game context - declare global variables - can be thought of as a frame by frame system - do init, set up window, init variables - register draw and kb callbacks - for each frame (draw callback) - do somthing (move things) - check somthing (collisions, new objects, winner looser) - update graphics (drawpix) - send draw event - motion is created by moving images incrementally across the screen one frame at a time - everytime kb event - do something (move things) - check somthing (collision with walls/etc) - done!