1 / 56

C++ Structs and Classes

C++ Structs and Classes. Readings (Nagler) 6.1-6.21, 7.1-7.6, 7.8, 7.12-7.16. C++ Structures: Classes. In C++, the concept of structure has been generalized in an object-oriented sense: classes are types representing groups of similar instances

sellsj
Download Presentation

C++ Structs and Classes

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C++ Structs and Classes Readings (Nagler) 6.1-6.21, 7.1-7.6, 7.8, 7.12-7.16

  2. C++ Structures: Classes • In C++, the concept of structure has been generalized in an object-oriented sense: • classes are types representing groups of similar instances • each instance has certain fields that define it (instance variables) • instances also have functions that can be applied to them (represented as function fields) -- called methods • the programmer can limit access to parts of the class (to only those functions that need to know about the internals)

  3. Outline Classes in C++ access modifiers: private, public, protected struct versus class class methods defined defined separately inlining static instance variables accessors mutators managers default ctor, dtor, copy ctor, other ctors

  4. C structs • As you remember from your C programming, it is possible to declare data structures that group related items. • For example, you could declare a structure called Student to store data related to a student (id, gpa, class)

  5. #include <stdio.h> typedef struct { int id; float gpa; char class; } Student; void main() { Student s1; printf(”Enter:\n”); printf(" ID#: "); scanf("%d",&s1.id); printf(" GPA: "); scanf("%f",&s1.gpa); printf(" Class: "); scanf(" %c",&s1.class); printf(”S#%d (%c) gpa = %.3f\n",s1.id,s1.class,s1.gpa); } Structure Example

  6. Student structure • Your student structure could be used to declare variables of type Student • Student s1; • It’s data members could be referenced in one of two ways, either using the membership operator ‘.’ or the pointer field operator ‘->’. • Example: s1.id = 12345;

  7. C++ advancements • C++ enhances the ability of structures to represent real-world objects in several ways. • It does this by allowing you to declare more powerful ‘structs’ that C++ calls ‘classes’ • The following example illustrates the differences and advantages of classes:

  8. A Robot struct • You wish to create a data structure that will embody all of the characteristics of a robot. • These characteristics are • 1. It’s location on a grid (x and y coordinates) • 2. The direction it is facing • Given these, your program will give the robot instructions to help it navigate around in a 2-d spatial field.

  9. T R Robot R must get to Target T

  10. You declare a simple structure: struct Robot { float locX; float locY; float facing; }; Robot r1; What if you never want locX or locY to be negative? Someone unaware of your restriction could set: r1.locX = -5; and you have a problem! A Motivating Example

  11. Robot modifications • To prevent locX from ever being negative we must somehow prevent anyone using our struct from directly assigning a value to locX. • We can accomplish this by forcing all assignments to happen through a small function we will write that can verify that changes are correct before locX is altered.

  12. Member functions • C++ allows you to put functions as well as data items into a structure. • A simple verification function might be: • void setX(float n) { if (n > 0) locX = n; }; • When added to the struct, this function becomes part of the structure and is called from variables that are instances of the structure (see next slide)

  13. Structures with member functions struct Robot { float locX; float locY; float facing; void setX(float n) { if (n > 0) locX = n; } }; Robot r1; r1.setX(5);

  14. Problems with member functions • The biggest problem with this use of member functions is that any program that adopts our robot structure can still ignore it and directly change locX! • r1.locX = -5; // still legal, bypasses setX(5)

  15. Structures with private parts • By default, all data members and all member functions of structures are ‘public’. • They can be accessed directly by client code. • But, the keyword ‘private’ can be used to designate certain data members and/or member functions as off-limits to outside programs.

  16. Use of public and private struct Robot { public: // operations void setX(float n) { if (n > 0) locX = n; } private: // data state float locX; float locY; float facing; }; Robot r1; r1.setX(5);

  17. Advantages of private section • With the structure divided into public and private parts we have now hidden some of its features from the outside world. • For example: • r1.locX = -5; // is not allowed • r1.locX = 5; // is also not allowed! • There is now no way to change locX without going through the public function setX().

  18. Data hiding • Using ‘private’ to hide data is an important tool in object oriented programming. • It allows for more easily debugged and maintained code because errors and modifications are localized. • Client code programs need only be aware of the type’s interface specification (they need to know about setX())

  19. Classes • A ‘class’ is like a struct that defaults to ‘private’ instead of ‘public’ • In C++ we will use classes for all of the ADTs that we implement.

  20. Robot class class Robot { public: // operations void setX(float n) { if (n > 0) locX = n; } private: // data state float locX; float locY; float facing; }; Robot r1; r1.setX(5);

  21. class ClassName { access_modifier1: field11_definition; field12_definition; … access_modifer2: field21_definition; field22_definition; … }; ClassName is a new type (just as if declared as struct with typedef in C) Possible access modifiers: public private protected Fields following a modifier are of that access until the next modifier is indicated Fields can be variables (as in C structures) or functions General Class Definition in C++

  22. An improved Robot Class class Robot { public: float getX() { return locX; } float getY() { return locY; } float getFacing() { return facing; } void setFacing(float f) { facing = f; } void setLocation(float x, float y); private: float locX; float locY; float facing; };

  23. private Access Modifier • Fields marked as private can only be accessed by functions that are part of that class • In the Robot class, locX, locY, and facing are private float fields, these fields can only be accessed by functions that are in class Robot (getX, getY, getFacing, setFacing, setLocation) • Example: void useRobot() { Robot r1; r1.locX = -5; // Error

  24. public Access Modifier • Fields marked as public can be accessed by anyone • In the Robot class, the methods getX, getY, etc. are public • these functions can be called by anyone • Example: void useRobot() { Robot r1; r1.setLocation(-5,-5); // Legal to call

  25. struct versus class • In C++ struct and class can be used interchangeably to create a class with one exception • What if we forget to put an access modifier before the first field? struct Robot { OR class Robot { float locX; float locX; In a class, until an access modifer is supplied, the fields are assumed to be private In a struct, the fields are assumed to be public

  26. What about protected? • C++ allows users to create classes based on other classes: • a FordCar class based on a general Car class • idea: the general Car class has fields (variables and functions that describe all cars) • the FordCar class then uses the fields from the general Car class and adds fields specific to FordCars • done with inheritance • public fields are inherited (as public) • private fields are not inherited • protected fields are like private, but can be inherited

  27. Class Methods • Functions associated with a class are declared in one of two ways: ReturnType FuncName(params) { code } • function is both declared and defined (code provided) ReturnType FuncName(params); • function is merely declared, we must still define the body of the function separately • To call a method we use the . form: classinstance.FuncName(args); FuncName is a field just like any other field in the structured variable classinstance

  28. Defined Methods class Robot { public: float getX() { return locX; } }; Robot r1; • The function getX is defined as part of class Robot • To call this method: cout << r1.getX() << endl; // prints r1’s locX • Why define the method this way? • Implicitly inline

  29. Inline Functions • In an inline function, the C++ compiler does not make a function call, instead the code of the function is used in place of the function call (and appropriate argument substitutions made) • Why? • Inline functions don’t have the overhead of other functions • Things like accessing/changing fields of a class instance should be fast • Including the definition of a function is an implicit request to make a function inline

  30. Inline Requests • Not all requests to make a function inline are honored • generally C++ examines the complexity of the function and the use of parameters in the function • should only request inline definition for short functions • Can also explicitly request to make class methods and other functions inline (add inline keyword before return type in function declaration and definition)

  31. Aside: A Global Inline Function • Use inline before return type: inline char upcase(char ch) { if ((ch >= ‘a’) && (ch <= ‘z’)) return (ch + (‘A’ - ‘a’)); else return ch; } cin >> option; if (upcase(option) == ‘Y’) ...

  32. Defining Methods Separately • For methods that are declared but not defined in the class we need to provide a separate definition • To define the method, you define it as any other function, except that the name of the function is ClassName::FuncName :: is the scope resolution operator, it allows us to refer to parts of a class or structure

  33. A Simple Class class Robot { public: void setLocation(float x, float y); private: float locX; float locY; float facing; }; void Robot::setLocation(float x, float y) { if ((x < 0.0) || (y < 0.0)) cout << “Illegal location!!” << endl; else { locX = x; locY = y; } }

  34. Explicitly Requesting Inline class Robot { public: inline void setLocation(float x, float y); }; inline void Robot::setLocation(float x, float y) { if ((x < 0.0) || (y < 0.0)) cout << “Illegal location!!” << endl; else { locX = x; locY = y; } }

  35. Referring to Class Fields void Robot::setLocation(float x, float y) { if ((x < 0.0) || (y < 0.0)) cout << “Illegal location!!” << endl; else { locX = x; locY = y; } } • What are locX and locY in setLocation?? • Since a class function is always called on a class instance, locX, locY are those fields of that instance • Example: Robot r1; Robot r2; r1.setLocation(5,5); // locX is from r1 r2.setLocation(3,3); // locY is from r2

  36. Types of Class Methods Generally we group class methods into three broad categories: accessors - allow us to access the fields of a class instance (examples: getX, getY, getFacing), accessors do not change the fields of a class instance mutators - allow us to change the fields of a class instance (examples: setLocation, setFacing), mutators do change the fields of a class instance manager functions - specific functions (constructors, destructors) that deal with initializing and destroying class instances (more in a bit)

  37. Accessors and Mutators Why do we bother with accessors and mutators? • Why provide getX()?? Why not just make the locX field publicly available? • By restricting access using accessors and mutators we make it possible to change the underlying details regarding a class without changing how people who use that class interact with the class

  38. Example • What if I changed the robot representation so that we no longer store locX and locY, instead we use polar coordinates (distance and angle to location)? • If locX is a publicly available field that people have been accessing it, removing it will affect their code • If users interact using only accessors and mutators then we can change things without affecting their code

  39. Rewritten Robot Class class Robot { public: float getX() { return dist * cos(ang); } float getY() { return dist * sin(ang); } void setLocation(float x, float y); private: float dist; float ang; }; void Robot::setLocation(float x, float y) { if ((x < 0.0) || (y < 0.0)) cout << “Illegal location!!” << endl; else { dist = sqrt(x * x + y * y); ang = atan2(y,x); } }

  40. Object-Oriented Idea • Declare implementation-specific fields of class to be private • Provide public accessor and mutator methods that allow other users to connect to the fields of the class • often provide an accessor and mutator for each instance variable that lets you get the current value of that variable and set the current value of that variable • to change implementation, make sure accessors and mutators still provide users what they expect

  41. Static Instance Variables • C++ classes may also contain, static instance fields -- a single field shared by all members of a class • Often used when declaring class constants (since you generally only need one copy of a constant) • To make a field static, add the static keyword in front of the field • can refer to the field like any other field (but remember, everybody shares one copy) • static variables are also considered to be global, you can refer to them without an instance • static fields can be initialized (unlike other fields)

  42. Static Fields Example class Robot { public: static int numRobots = 0; static const float minX = 0.0; static const float maxX = 100.0; void initializeRobot() { numRobots++; } void setLocation(float x, float y); } void Robot::setLocation(float x, float y) { if ((x < minX) || (x > maxX)) … }

  43. Static Fields as Global Variables • One can examine public static fields of a class outside of that class using the form: ClassName::StaticFieldName • Example: void main() { Robot r1, r2; r1.initializeRobot(); r2.initializeRobot(); cout << Robot::numRobots << “ robots.\n”;

  44. The Need for Manager Functions • To make the previous program work we have to explicitly call the routine initializeRobot, wouldn’t it be nice to have a routine that is automatically used to initialize an instance -- C++ does • C++ provides for the definition of manager functions to deal with certain situations: constructors (ctor) - used to set up new instances • default - called for a basic instance • copy - called when a copy of an instance is made (assignment) • other - for other construction situations destructors (dtor) - used when an instance is removed

  45. When Managers Called void main() { Robot r1; // default ctor (on r1) Robot r2; // default ctor (on r2) Robot* r3ptr; r3ptr = new Robot; // default ctor on // Robot object r3ptr points to r2 = r1; // copy ctor delete r3ptr; // dtor } // dtor (on r1 and r2) when main ends

  46. The Default Constructor (ctor) • A default constructor has no arguments, it is called when a new instance is created • C++ provides a default ctor that initializes all fields to 0 • To write your own, add following to your class: class MyClass { public: … MyClass() { // repeat class name, no code here // return type } }

  47. Example Default ctor class Robot { public: static int numRobots = 0; Robot() { numRobots++; locX = 0.0; locY = 0.0; facing = 3.1415 / 2; } private: float locX; float locY; float facing; }

  48. Destructor (dtor) • A destructor is normally not critical, but if your class allocates space on the heap, it is useful to deallocate that space before the object is destroyed • C++ provides a default dtor that does nothing • can only have one dtor • To write your own, add following to your class: class MyClass { public: … ~MyClass() { code here } }

  49. Example dtor class Robot { public: char *robotName; Robot() { robotName = 0; } void setRobotName(char *name) { robotName = new char[strlen(name)+1]; strcpy(robotName,name); } ~Robot() { delete [] robotName; } }

  50. The Copy ctor • A copy constructor is used when we need a special method for making a copy of an instance • example, if one instance has a pointer to heap-allocated space, important to allocate its own copy (otherwise, both point to the same thing) • To write your own, add following to your class: class MyClass { public: … MyClass(const MyClass& obj) { code here } }

More Related