230 likes | 358 Views
Structs / Classes. CS31 Discussion. OUTLINE: Structures Structures and pointers Member functions / Classes. TA: Peter Wu Slides adopted from a previous CS31 (Carey’s) class. Structures.
E N D
Structs / Classes CS31 Discussion • OUTLINE: • Structures • Structures and pointers • Member functions / Classes TA: Peter Wu Slides adopted from a previous CS31 (Carey’s) class
Structures We can use the “structure” feature in C++ to define a new data type (like int, string, double) that can store a student’s name, ID and GPA all in one variable. First, write the word struct. Then we give our new struct a name… struct STUDENT { } Then we specify all of the fields that our new structure contains in between { and } string name; int ID; double GPA; Finally, we add a semicolon ; at the end. ; This defines an entirely new data type, like string, that we can now use in our program.
Structures STUDENT is not a variable. Instead it is a new data type(like int or string) Just as this line creates a new string called s. This line creates a new STUDENT variable called t. #include <iostream> struct STUDENT { string name; int ID; double GPA; }; main() { strings; STUDENTt; t.name = “Joe Bruin”; t.ID = 113353948; t.GPA = 3.99; … .
Structures s “” t name “” 113353948 3.99 ID -721 GPA 7.11 #include <iostream> struct STUDENT { string name; int ID; double GPA; }; main() { strings; STUDENTt; t.name = “Joe Bruin”; t.ID = 113353948; t.GPA = 3.99; … The variable t has 3 sub-variables in it: name, ID_number and GPA. We can set t’s fields using this syntax: t .fieldname = value; . “Joe Bruin”
Structures Typically, you define new structure types outside of all functions. After you define a new structure type, you can create variables with it throughout your program. Once we define our new structure type like STUDENT, we can use it like any other traditional data type. struct STUDENT { string name; int ID; double GPA; }; void levelup(STUDENT &x) { x.GPA++; } main() { STUDENT UCLA[50000]; STUDENT a,b,*ptr; levelup(a); ...
Structure Layout in Memory c1 .name Jeep0 .hp .doors c2 ... 00001000 00001001 00001002 00001003 00001004 00001005 00001006 00001007 00001008 00001009 00001010 00001011 00001012 00001013 00001014 00001015 struct Car { char name[6]; int hp; int doors; }; main() { Car c1, c2; strcpy(c1.name,“Jeep”) c1.hp = 140; c1.doors = 2; strcpy(c2.name,“HotWh”) c2.hp = 30; c2.doors = 3; … 140 2
Structures and Pointers c1 .name Jeep0 .hp .doors 00001000 00001001 00001002 00001003 00001004 00001005 00001006 00001007 00001008 00001009 00001010 00001011 00001012 00001013 00001014 00001015 00001016 00001017 struct Car { char name[6]; int hp; int doors; }; main() { Car c1; Car *p1; p1 = &c1; p1->hp = 140; p1->doors = 2; strcpy(p1->name,”Jeep”); } This line says: Find where p1 points… Then locate p1’s hp field. 140 Then store a value of 140 in this field. 2 p1 1000 Use a –> to access a structure variable via a pointer.
What’s Wrong With It? pCar name: hp: doors: 00000000 00000001 struct Car { char name[6]; int hp; int doors; }; void main(void) { Car *pCar; pCar->hp = 250; } … 00002000 00002001 00002002 00002003 00002004 00002005 00002006 00002007 00002008 00002009 00002010 459292 KABOOM! … Remember: You have to point your pointer at a variable before using it to set values!!! Your CS homework?? int main() { cout << “I love CS!\n” 250
Passing Structures to Functions (by Value) my_car blah .hp .doors .doors .hp Question: How are struct variables passed to a function? struct Car { int hp; int doors; }; 00001000 00001001 00001002 00001003 00001004 00001005 00001006 00001007 00001008 00001009 00001010 00001011 00001012 00001013 00001014 00001015 00001016 00001017 140 140 2 void ProcessCar(Car blah) { cout << blah.hp << endl; blah.doors++; // lets change it } main() { Car my_car; my_car.hp = 140; my_car.doors = 2; ProcessCar(my_car); cout << my_car.doors; 2 140 Answer: If you pass your struct variable by value, a copy of the variable is made and sent to the function… 3 2
Passing Structures to Functions (by ref) my_car .hp .doors blah Now lets see how to pass struct variables by reference… struct Car { int hp; int doors; }; 00001000 00001001 00001002 00001003 00001004 00001005 00001006 00001007 00001008 00001009 00001010 00001011 00001012 00001013 00001014 00001015 00001016 00001017 140 140 3 void ProcessCar(Car & blah) { cout << blah.hp << endl; blah.doors++; // lets change it } main() { Car my_car; my_car.hp = 140; my_car.doors = 2; ProcessCar(my_car); cout << my_car.doors; 3 2 Notice: We still use the . to access fields within the referenced struct variable!
Passing Structures to Functions (by pointer) my_car .hp .doors blah Now lets see how to pass struct variables by pointer… struct Car { int hp; int doors; }; 00001000 00001001 00001002 00001003 00001004 00001005 00001006 00001007 00001008 00001009 00001010 00001011 00001012 00001013 00001014 00001015 00001016 00001017 140 140 3 void ProcessCar(Car * blah) { cout << blah->hp << endl; blah->doors++; // lets change it } main() { Car my_car; my_car.hp = 140; my_car.doors = 2; ProcessCar(&my_car); cout << my_car.doors; 1000 3 2 1000 Notice: With pointers, we use the -> to access fields within the pointed-to struct variable! 1000
Passing Structs to Functions Question: So what’s the best way to pass a struct variable to a function? Answer: Well, it’s fastest to use a reference or a pointer. If you pass by value, it will duplicate the whole structure variable which may be slow! Use the const keyword if you don’t want the target function to modify your struct’s fields… void ProcessCar(const Car * blah) { cout << blah->hp << endl; blah->doors++; // ERROR! }
Reference: Structure Composition porsche doors hp watts decibels sony Sometimes you want to put one structure variable inside another… This is called composition. struct Stereo { int watts; double decibels; }; main() { Car porsche; porsche.hp = 250; porsche.sony.watts = 150; ... cout << porsche.sony.watts; } struct Car { int hp; int doors; Stereo sony; };
Using -> vs * and . Any time you have code that looks like this: ptr->field = value; It can be rewritten like this… (*ptr).field = value;
Intro to Member Functions area a r width height Consider the following structure and associated function(s). struct Rect { int width; int height; }; int GetArea(Rect &a) { int area = a.width * a.height; return(area); } struct Rect { int width; int height; }; 10 20 200 int main(void) { Rect r; r.width = 10; r.height = 20; cout << GetArea(r); 10 * 20 200
Classes ) class Convention: A class is basically a struct with built-in functions in addition to field variables. (used interchangeably in CS31 by us/Smallberg) struct Rect { int width; int height; }; int GetArea(Rect &a) { int area = a.width * a.height; return(area); } struct Rect { int width; int height; }; int width; int height; }; int GetArea(Rect &a) { int area = a.width * a.height; return(area); }
Using a Class r int main(void) { Rect r; r.width = 10; r.height = 20; cout << r.GetArea(); area int GetArea() { int area = width * height; return(area); } width height class Rect { int GetArea() { int area = width * height; return(area); } int width; int height; }; Output: 200 * 200 10 10 20 20 200
Using a Class int GetArea() { int area = width * height; return(area); } width height int GetArea() { int area = width * height; return(area); } width height r s int main(void) { Rect r, s; r.width = r.height = 5; s.width = s.height = 7; cout << r.GetArea(); cout << s.GetArea(); area area class Rect { int GetArea() { int area = width * height; return(area); } int width; int height; }; Output: 25 49 5 * 5 25 25 5 5 7 * 7 49 49 7 7 25 49
Using a Class int GetArea() { int area = width * height; return(area); } width height int GetArea() { int area = width * height; return(area); } width height r s int main(void) { Rect r, s; r.width = r.height = 5; s.width = s.height = 7; cout << r.GetArea(); cout << s.GetArea(); area Use local variables for temporary calculations in your member functions. Use member variables when your class needs to store the values permanently. GetArea is a “member function” of r. To call a member function of r, write: r.functionname(params); r and s are variables. In C++ lingo, you can also call them “instances”: “r is an instance of a Rect. s is an instance of Rect too.” This time, we’re calling the GetArea function of s. Since we’re in r, GetArea works on r’s member variables: r.width and r.height… The area variable is a local variable, just like in regular functions. It disappears once our function ends! class Rect { int GetArea() { int area = width * height; return(area); } int width; int height; }; r.width and r.height are called “member variables” r has its own copies of both width and height. Clearly, s has its own copies of width and height too. 5 5 5 5 49 7 7 7 7
Classes class Rect { int GetArea() { int area = width * height; return(area); } We can add as many functions as we like to our class… void Initialize(int startW, int startH) { width = startW; height = startH; } int width; int height; }; int main(void) { Rect r; r.width = 10; r.height = 20; cout << r.GetArea(); r.Initialize(10,20);
Classes Oh, and there’s two more things we have to do to make our class correct… #1: The public keyword means: these functions can be accessed by any part of our program. class Rect { int GetArea() { int area = width * height; return(area); } public: I can call Rect’s member functions GetArea and Initialize since they’re public! void Initialize(int startW, int startH) { width = startW; height = startH; } int main(void) { Rect r; r.Initialize(10,7); cout << r.GetArea(); private: int width; int height; };
Classes I’m a member function, so I can access width and height. #2: The private keyword means: these variables may only be accessed by the class’s member functions class Rect { int GetArea() { int area = width * height; return(area); } public: I’m a member function too, so I can access width and height. Outside functions may not access private variables, however! width * height I’m not a member function of Rect so I can’t access its private variables! void Initialize(int startW, int startH) { width = startW; height = startH; } widthheight int main(void) { Rect r; r.Initialize(10,7); cout << r.GetArea(); private: int width; int height; }; r.width = 10; // ERROR!
Public vs Private • More details in another lecture / discussion