Introduction to C++ Prof. David Tanzer tanzer@cs.nyu.edu Copyright © 2003 All Rights Reserved General Points about C++ • • • • • • Widely available Standardized, highly portable Powerful abstractions Generates efficient code Strongly typed Less flexible than interpreter Outline • C features • C++ features • Application Compilation Model • • • • • • • Source code Header files Compiler Object code Libraries Linker Executable Simple Program #include <iostream.h> main() { int x,y; cout << “enter x,y” << endl; cin >> x; cin >> y; cout << “average = “ << (x+y) / 2.0 << end; } Basic Types • • • • • int bool float double char If-Then-Else int x; cin >> x; if (x > 0) { cout << “positive input!” << endl; cout << “value = “ << x; } else cout << “error: negative input!” << endl; While Loop // estimate the square root of n int i = 0; while (i*i < n) i = i + 1; cout << “square root is near” << i << endl; For-Loop // print the first 99 squares int i; for (i = 1; i < 100; i++) { cout << “i: “ << i; cout << “squared: “ << i * i << endl; } Loops – General Form • • • • • while (expression) statement; do statement while (expression); for (init; test; update) statement; x = y + z; // simple statement {x = 1; y = 2;} // compound statement Expressions • • • • • • x + y, x – y, x * y, x / y, x % y x == y, x != y, x < y, x > y, x <= y, x >= y ~x, x & y, x | y, x ^ y x << nbits, x >> nbits !exp, exp && exp, exp || exp test_exp ? then_exp : else_exp Increment Operators • • • • • • • x = x + 100; x += 100; x *= 2; x++; x--; ++x; --x; Break Statement while (1) { cin >> nextval; if (nextval< 0) break; process(nextval); } cout << “error: negative input” << endl; Continue Statement while (1) { cin >> nextval; if (nextval< 0) continue; // skip the bad input process(nextval); } Functions float avg(float x, float y) { cout << “computing the average...” << endl; return (x + y) / 2.0; } float avg4(float x, float y, float z, float w) { return avg(avg(x,y), avg(z,w)); } Local and Global Scopes int x = 5; int y = 6; float funct(float arg) { int y = 7; // shadows the global y cout << x << endl; // prints 5, from global cout << y << endl; // prints 7, from local Argument Passing void avg(float x, float y, float &z) { // x,y are passed by value; z by reference z = (x + y) / 2; } ... float outval; avg(1.3, 2.2, outval); // outval is modified Function Overloading float funct(int x) { ... return z;} float funct(int x, int y) { ... return z;} ... funct(20); // uses the first definition funct(20,30); // uses the second Type Conversion (casting) int x = 55; float y1 = (int) x; // explicit conversion float y2 = x; // implicit conversion float f = 3.4; x = (int) f; // now x = 3 int* iptr = &x; // iptr = address of x void* ptr = (void*) iptr; // typeless pointer Structures struct {float x; float y;} vec; vec.x = 10.0; vec.y = 20.0; float mag = magnitude(vec); struct {float x; float y;} vec2; vec2 = vec; Typedef typedef double real; real x = 1.1; typedef struct {float x; float y;} vector; vector v, w, x; v = inputVector(“enter v”); w = inputVector(“enter w”); outputVector(addvector(v,w)); addvector -- implementation vector addvector(vector v, vector w) { vector result; result.x = v.x + w.x; result.y = v.y + w.y; return result; } Arrays int x[10]; // create storage for 10 ints x[0] = 111; x[1] = 555; inputValues(x,10); int sum = 0; for (int i = 0; i < 10; i++) sum = sum + x[i]; vector buffer[10]; Strings char name[100]; name[0] = ‘A’; name[1] = ‘L’; name[2] = 0; cout << “name = “ << name << endl; cin >> “what’s your name?” >> name; for (int i = 0; name[i] != 0; i++) ; cout << “# of chars = “ << i << endl; Pointers int x; int* y; // pointer to an integer x = 5; y = &x; // now y points to x cout << “value = “ << *y; // prints 5 (*y)++; // increments x Pointer Arithmetic int stringlen(char* charbuf) // array converted to ptr { int count = 0; while (*charbuf != 0) { charbuf++; count++; } return count; } Pointer Crashes int* x; x = 0; *x = 55; // crash! int buf[10]; buf[10] = 99; // crash! Arguments from the O.S. int main(int argc, char** argv) { cout << “nargs = “ << argc << endl; char* progname = argv[1]; int arg1 = atoi(argv[1]); cout << “double the input = “ << 2 * arg1; return 0; // tell the o.s. there was no err } Classes • • • • • • • C-structure plus member functions Encapsulation Inheritance Polymorphism Access control Modular design Software reusability Encapsulation class vector { float x, y; public: vector(float xval, float yval) {x=xval; y=yval;} void vector scale(float scaleval) { x *= scaleval; y *= scaleval; } }; vector v(10,20); // calls the constructor v.scale(5) // calls the encapsulated funct Using Object Pointers class vector { ... vector* scale(float scaleval); ... }; vector* vector::scale(float scaleval) { return new vector(x*scaleval, y*scaleval); } vector* v = new vector(10,20); vector* w = v->scale(10); delete v; A Class for Images class image { int npoints; vector* points; public: image(File* datafile) { npoints = linecount(datafile); points = new vector[npoints]; for (i = 0; i < npoints; i++) points[i] = parseRow(i,datafile); } ~image() {delete points;} Image Class Cont’d void shift(float xoff, float yoff); void scale(float scaleval); void dump(char* outfname); }; // end class void image::shift(float xoff, float yoff) { for (i = 0; i < npoints; i++) points[i].shift(xoff,yoff); } Using the Image Class File* f = new File(“/home/dave/input.img”); image* i = new image(f); i->scale(3.4); i->shift(1.3,7.7); i->dump(“/home/dave/output.img”); delete i; Inheritance • • • • • • Create a new class which extends another Base class, derived class Derived inherits members of base Example: student is a person Derived class is more specific Hence may introduce special members Application of Inheritance • Want a class for images with a focus point • Don’t want to disturb or complicate the existing image class • Solution: derive a class from image • Derived class will store the focus coords • Which methods should be inherited? • Which methods should be overriden? Class for Images with Focus class image2: public image { float xfoc, yfoc; public: image2(File* datafile, int xf, int yf) : xfoc (xf), yfoc (yf), image(datafile) {} void scale(float scaleval); // reimplement // we can inherit shift(xoff,yoff) Overriding a Method image2::scale(float scaleval) { for (int i = 0; i < npoints; i++) { float deltaX = points[i].getx() – xfoc; points[i].setx(xfoc + scaleval * deltaX); ... [similarly for Y] }} Polymorphism • Function is polymorphic if the types of its arguments may vary • Example: length of an array • Polymorphic functions may be defined in terms of other polymorphic functions – nitems(matrix) := nrows(matrix)*ncols(matrix) Virtual Functions • For implementing polymorphism in C++ • Base class contains “virtual functions” – Not implemented in the base class – Implementation given in each derived class • Calls to virtual functions are resolved at runtime • Higher-level polymorphic functions may be built using calls to virtual functions A Virtual Base Class class num { virtual num* scale(num* x) = 0; num* power(int exponent) { num* result = this; for (int i = 1; i < exponent; i++) result = result->scale(this); return result; } }; Realizations of the Virtual Class class doubNum : public num { double val; public: doubNum(double v) {val = v;} num* scale(num* x) { // doubNum* d = (doubNum*) x; // assumption return new doubNum(d->val * val); } Using the Number Class doubNum* d = new doubNum(1.234); doubNum* d_cubed = d->power(3); complexNum* c = new complexNum(3,1.2); complexNum* c_cubed = c->power(3); // the SAME power code is executed for both Extending an Intepreter • C++ generates fast code • But lacks runtime flexibility of interpreter • Synthesis: write primitives in C++ and link into interpreter • Writing the interface code is fairly tedious • SWIG can automatically generate: – Interpreter interface code – Shadow classes Real Application • Financial variables represented by large matricies: – organized by stock, date • Too large to fit into memory • Want to do matrix transforms, like: – n-day moving average – n-day returns • Design a flexible and efficient system