> price; cout << "Tax rate (0.0 for default): "; cin >> rate; if (rate == 0.0) printAmt(calculateTax(price)); else printAmt(calculateTax(price, rate)); } void printAmt(float amt) { cout.setf(ios::fixed); cout.precision(2); cout << "$" << amt << endl; } [Show / Discuss Call Stack] [Talk about scope / lifetime]"> > price; cout << "Tax rate (0.0 for default): "; cin >> rate; if (rate == 0.0) printAmt(calculateTax(price)); else printAmt(calculateTax(price, rate)); } void printAmt(float amt) { cout.setf(ios::fixed); cout.precision(2); cout << "$" << amt << endl; } [Show / Discuss Call Stack] [Talk about scope / lifetime]">

Presentation is loading. Please wait.

Presentation is loading. Please wait.

Lecture 01d: C++ review Topics: functions scope / lifetime preprocessor directives header files C structures ("simple classes")

Similar presentations


Presentation on theme: "Lecture 01d: C++ review Topics: functions scope / lifetime preprocessor directives header files C structures ("simple classes")"— Presentation transcript:

1 Lecture 01d: C++ review Topics: functions scope / lifetime preprocessor directives header files C structures ("simple classes")

2 Part I: functions Basic syntax – Declaration (if a function call comes before the definition) return-value func_name([parameters]); – Body return-value func_name(parameters) body The return type can be void if the function isn't meant to return anything.

3 Example void printAmt(float amt);// prototype float calculateTax(float base, float rate=0.07f) { float total; total = base * (1.0f + rate); return total; } int main() { float price, rate; cout << "Enter price: "; cin >> price; cout << "Tax rate (0.0 for default): "; cin >> rate; if (rate == 0.0) printAmt(calculateTax(price)); else printAmt(calculateTax(price, rate)); } void printAmt(float amt) { cout.setf(ios::fixed); cout.precision(2); cout << "$" << amt << endl; } [Show / Discuss Call Stack] [Talk about scope / lifetime]

4 Pointer parameters Useful because: – Passing a pointer is often much cheaper than copying a large argument (e.g. objects) – Allows us to modify what the pointer points to. Especially useful if we want to "return" more than 1 value. void foo(ReallyBigDataStructure * d)// only copies 4 bytes! {} void fooBad(ReallyBigDataStructure s) // copies mucho bytes { } int getImageSize(SDL_Surface * s, int * w, int * h) {// s is input; w and h are "return" values int error = 0; if (s == NULL)error = 1; else { *w = s->w; *h = s->h; } return error; }

5 Another interpretation of pointer parameters Syntactically the same as last slide. But since a pointer = address, it could be pointing to an array – Documentation is important! // p is a pointer to an array of 3 values. This // function returns the sum of those 3 values. int func(int * p) { return p[0] + p[1] + p[2]; } int main() { int values[3] = {5, 7, 13}, result; result = func(values); } #include using namespace std; // p is a pointer to a single integer. This func // sets that value to the current hour and returns // the current minutes. int func(int * p) { time_t t = time(0); struct tm * now = localtime(&t); *p = now->tm_hour; return now->tm_min; } int main() { int hour, minutes; minutes = func(&hour); }

6 Reference Parameters C++ only Really does pass-by-pointer, but hides it int getImageSize(SDL_Surface * s, int & w, int & h) { int error = 0; if (s == NULL) error = 1; else { w = s->w;// Note: de-reference is done... h = s->h;//...automatically } return error; }

7 Part II: Scope Levels Global scope – Defined outside all blocks – Accessible anywhere (might need extern) File scope – Like global, but with static qualifier – Only accessible in this file. Local scope (parameters, local variables) Block scope – "closest" blocks are used first

8 Example int x = 15; // global scope static float y = 1.2;// file scope int func(int a, float b) // a & b have local scope { double c = a * 2 + b / 0.5 + x;// c too... if (c < 10.0) { int y;// block scope //... } return (int)c; } int main() { int x;// Local scope – masks global x x = func(x, y); }

9 static modifier Two uses (a third in classes) – To indicate file scope – To make a "persistent" variable in a function static int x; // file scope void func() { static int counter = 0; // A "persistent" variable. Only initialized once counter++; }

10 Part III: Pre-processor directives Entirely textual (not C/C++ code)! Are completely evaluated before the compiler starts. All start with a pound (#)

11 Example #if _WIN32 #include #endif #include "my_file.h" #define REAL float #define VERBOSE void doSomething() { #ifdef VERBOSE cout << "Starting 'doSomething'..."; #endif // *really* do something #if VERBOSE cout << "done! time="; #ifdef _DEBUG cout << calculateTime() << endl; #else cout << endl; #endif }

12 Macro's cont. Some lesser-used directives #undef Macro functions #define MIN(a, b) a < b ? a : b #define SFUNC(msg, funcName, eCode) cout << msg << "…" \ if (funcName() != 0) return eCode; \ cout << "done!\n"; Built-in macros (compiler dependent) __LINE__ __FILE__ _DEBUG _WIN32 _GCC __VERSION__

13 Part IV: Header files The compiler compiles all source files into object files The linker combines all object files (and other libraries) into the executable. Header files are useful to store "common" information which is (possibly) used in multiple places – function prototypes – other include files (iostream, …) – macros – [later] class declarations

14 Example #ifndef _MY_HEADER_H_// Not always necessary, but #define _MY_HEADER_H_// can prevent a 'multiple // declarations of "x" error.' #include using namespace std; void myFunc(int a, float b); // Other things... #endif

15 Part V: C-style structures Basically, a collection of data – Similarities to arrays: single name, multiple values – Differences from arrays: access individual values by name (structs) instead of by position (arrays) Can have different types of data (heterogeneous); array elements must be the same (homogeneous) Two parts: – defining the structure (a new type) – Creating variables of that type.

16 Example of structs // Part I: Define a type (could go in a.h file...) struct employeeData { string name; int id; float salary; };// <== don't forget the semi-colon! int main() { employeeData record;// Part II: Make variables employeeData record2;//...another one record.id = 15; record.name = "Joe Smith"; record.salary = 48000.0f; record2.id = 16;// Doesn't change record's data cout << "record.id = " << record.id << endl; }

17 Pointers to structures // employeeData struct defined as before void outputEData(employeeData * e) { //cout << (*e).name << endl;// ugly... cout name << endl;// much nicer! for (int i=0; i name.size(); i++) cout << "="; cout << "\n\tid = " << (*e).id << endl; cout salary << endl; } int main() { employeeData curRec; // curRec is filled in... outputEData(&curRec); }

18 Dynamic allocation of struct variables // employeeData structure is defined as before. int main() { employeeData * eptr = NULL; eptr = new employeeData; // allocates on heap eptr->name = "Jason"; eptr->id = 99; eptr->salary = 20000.0f; delete eptr;// Note: no brackets eptr = NULL;// Not required, but prevents // a dangling pointer. }

19 Pass by pointer, pass-by-value, and pass-by-reference The outputEData function uses pass- by-pointer We could also re- write it using pass- by-value [Advantages / Disadvantages of each] [Show stack for each] // pass-by-pointer void funcPBP(employeeData * e) {e->salary += 1.0f; } // pass-by-value void funcPBV(employeeData e) { e.salary += 1.0f; } // pass-by-reference void funcPBR(employeeData & e) { e.salary += 1.0f; } int main() { employeeData r1 = {“Joe”, 1, 200.0f}; employeeData r2 = {“Sue”, 2, 300.0f}; employeeData r3 = {“Bob”, 3, 400.0f}; funcPBP(&r1); funcPBV(r2); funcPBR(r3); cout << r1.salary << “\n”; // 201.0 cout << r2.salary << “\n”; // 300.0 cout << r3.salary << “\n”; // 401.0 }


Download ppt "Lecture 01d: C++ review Topics: functions scope / lifetime preprocessor directives header files C structures ("simple classes")"

Similar presentations


Ads by Google