Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 11: More About Classes and Object-Oriented Programming

Similar presentations


Presentation on theme: "Chapter 11: More About Classes and Object-Oriented Programming"— Presentation transcript:

1 Chapter 11: More About Classes and Object-Oriented Programming
Starting Out with C++ Early Objects Seventh Edition by Tony Gaddis, Judy Walters, and Godfrey Muganda

2 Topics 11.1 The this Pointer and Constant Member Functions 11.2 Static Members 11.3 Friends of Classes 11.4 Memberwise Assignment 11.5 Copy Constructors 11.6 Operator Overloading 11.7 Type Conversion Operators

3 Topics (continued) 11.8 Convert Constructors 11.9 Aggregation and Composition Inheritance Protected Members and Class Access Constructors, Destructors, and Inheritance Overriding Base Class Functions

4 11.1 The this Pointer and Constant Member Functions
- Implicit parameter passed to a member function - points to the object calling the function Is passed as a hidden argument to all non-static member functions Can be used to access members that may be hidden by parameters with same name const member function: - does not modify its calling object See pr11-01.cpp

5 Using the this Pointer {
Can be used to access members that may be hidden by parameters with the same name: class SomeClass { private: int num; public: void setNum(int num) { this->num = num; } };

6 Constant Member Functions
Declared with keyword const When const follows the parameter list, int getX()const the function is prevented from modifying the object. When const appears in the parameter list, int setNum (const int num) the function is prevented from modifying the parameter. The parameter is read-only.

7 11.2 Static Members Each instance of a class has its own copies of the class’s instance (member) variables Objects box1 and box2 of class Rectangle each have their own values for length and width Static member variable: One instance of variable for the entire class Shared by all objects of the class Static member function: Can be used to access static member variables Can be called before any class objects are instantiated See pr11-02.cpp, budget.h

8 Static Member Variables
Must be declared in class with keyword static: class IntVal { public: intVal(int val = 0) { value = val; valCount++ } int getVal(); void setVal(int); private: int value; static int valCount; };

9 Static Member Variables
2) Must be defined outside of the class: class IntVal { //In-class declaration static int valCount; //Other members not shown }; //Definition outside of class int IntVal::valCount = 0;

10 static member variable
Contents of Tree.h 1 // Tree class 2 class Tree 3 { 4 private: static int objectCount; // Static member variable. 6 public: // Constructor Tree() { objectCount++; } // Accessor function for objectCount int getObjectCount() const { return objectCount; } 14 }; // Definition of the static member variable, written 17 // outside the class. 18 int Tree::objectCount = 0; Static member declared here. Static member defined here. C++: Classes & Objects -2

11 C++: Classes & Objects -2

12 Three Instances of the Tree Class, Only One objectCount Variable
C++: Classes & Objects -2

13 Static Member Variables
3) Can be accessed or modified by any object of the class: Modifications by one object are visible to all objects of the class: IntVal val1, val2; valCount 2 val1 val2

14 Static Member Functions
1)Declared with static before return type: class IntVal { public: static int getValCount() { return valCount; } private: int value; static int valCount; };

15 Static Member Functions
2) Can be called independently of class objects, through the class name: cout << IntVal::getValCount(); 3) Because of item 2 above, the this pointer cannot be used 4) Can be called before any objects of the class have been created 5) Used mostly to manipulate static member variables of the class See pr11-03.cpp, budget2.cpp, and budget2.h

16 Modified Version of Tree.h
1 // Tree class 2 class Tree 3 { 4 private: static int objectCount; // Static member variable. 6 public: // Constructor Tree() { objectCount++; } // Accessor function for objectCount static int getObjectCount() { return objectCount; } 14 }; // Definition of the static member variable, written 17 // outside the class. 18 int Tree::objectCount = 0; Now we can call the function like this: cout << "There are " << Tree::getObjectCount()<< " objects.\n"; C++: Classes & Objects -2

17 Budget Class version 1 Budget class gathers budget information from all the divisions of a company The static member, corpBudget, holds the overall corporate budget The function addBudget adds the passed amount to the division total as well as the corporate total C++: Classes & Objects -2

18 Budget version 1 In main, we call getCorpBudget by specifying an object of the Budget class: divisions[0].getCorpBudget() Note that a static method can not specify const You can also call the function as Budget::getCorpBudget() but then the function would have to be static and could not be const C++: Classes & Objects -2

19 Budget version 1 #ifndef BUDGET_H #define BUDGET_H class Budget { private: static double corpBudget; // Static member double divisionBudget; // Instance member public: Budget() { divisionBudget = 0; } void addBudget(double b) { divisionBudget += b; corpBudget += b; } double getDivisionBudget() const { return divisionBudget; } double getCorpBudget() const // not defined static otherwise could not be const { return corpBudget; } // therefore requires an object to be called }; // Definition of static member variable corpBudget double Budget::corpBudget = 0; #endif C++: Classes & Objects -2

20 Budget version 1 C++: Classes & Objects -2
#include <iostream> #include <iomanip> #include "Budget.h" using namespace std; int main() { int count; // Loop counter const int NUM_DIVISIONS = 4; // Number of divisions Budget divisions[NUM_DIVISIONS]; // Array of Budget objects // Get the budget requests for each division. for (count = 0; count < NUM_DIVISIONS; count++) double budgetAmount; cout << "Enter the budget request for division "; cout << (count + 1) << ": "; cin >> budgetAmount; divisions[count].addBudget(budgetAmount); } // Display the budget requests and the corporate budget. cout << fixed << showpoint << setprecision(2); cout << "\nHere are the division budget requests:\n"; cout << "\tDivision " << (count + 1) << "\t$ "; cout << divisions[count].getDivisionBudget() << endl; cout << "\tTotal Budget Requests:\t$ "; cout << divisions[0].getCorpBudget() << endl; return 0; C++: Classes & Objects -2

21 Budget Class version 2 Here a static function, mainOffice, is found
This allows the inclusion of a budget for the main office in addition to the individual divisions The function can be called even before any objects of the Budget class have been instantiated C++: Classes & Objects -2

22 Budget version 2 #ifndef BUDGET_H #define BUDGET_H class Budget { private: static double corpBudget; // Static member variable double divisionBudget; // Instance member variable public: Budget() { divisionBudget = 0; } void addBudget(double b) { divisionBudget += b; corpBudget += b; } double getDivisionBudget() const { return divisionBudget; } double getCorpBudget() const { return corpBudget; } static void mainOffice(double); // Static member function }; #endif C++: Classes & Objects -2

23 Budget version 2 THIS IS FILE BUDGET.CPP #include "Budget.h" // Definition of corpBudget static member variable double Budget::corpBudget = 0; //********************************************************** // Definition of static member function mainOffice. * // This function adds the main office's budget request to * // the corpBudget variable. * void Budget::mainOffice(double moffice) { corpBudget += moffice; } C++: Classes & Objects -2

24 Budget version 2 #include <iostream> #include <iomanip> #include "Budget.h" using namespace std; int main() { int count; // Main office budget request double mainOfficeRequest; const int NUM_DIVISIONS = 4;// # of divisions //Get the main office's budget request. //No instances of Budget class have been defined cout << "Enter the main office's budget: "; cin >> mainOfficeRequest; Budget::mainOffice(mainOfficeRequest); // An array of Budget objects. Budget divisions[NUM_DIVISIONS]; // Get the budget requests for each division. for (count = 0; count < NUM_DIVISIONS; count++) double budgetAmount; cout << "Enter the division budget request "; cout << (count + 1) << ": "; cin >> budgetAmount; divisions[count].addBudget(budgetAmount); } // Display corporate and division budgets cout << fixed << showpoint<< setprecision(2); cout << "\nHere are the division budget requests:\n"; for (count=0; count<NUM_DIVISIONS; count++) { cout<<"\tDivision "<< (count+1)<< "\t$"; cout<<divisions[count].getDivisionBudget()<< endl; } cout << "\tTotal Budget Requests:\t$ "; cout << divisions[0].getCorpBudget()<< endl; return 0; C++: Classes & Objects -2

25 Budget version 2 What would you need to do in order to store the amount of the main office budget request as a static number and then print it out at the end of the report before the division budgets? Declare static variable mainOffice in Budget class Initialize mainOffice in Budget.cpp Add mainOffice += moffice; to addMainOffice Add double static getMainOffice() { return mainOffice; } to Budget.h C++: Classes & Objects -2

26 11.3 Friends of Classes Friend function: a function that is not a member of a class, but has access to private members of the class A friend function can be a stand-alone function or a member function of another class It is declared a friend of a class with the friend keyword in the function prototype of the class granting it access

27 Friend Function Declarations
Friend function may be a stand-alone function: class aClass { private: int x; friend void fSet(aClass &c, int a); }; void fSet(aClass &c, int a) c.x = a; } See pr11-04.cpp, auxil.h, budget3.h, auxil.cpp, and budget3.cpp

28 Friend Function Declarations
2) Friend function may be a member of another class: class aClass { private: int x; friend void OtherClass::fSet (aClass &c, int a); }; class OtherClass { public: void fSet(aClass &c, int a) { c.x = a; }

29 friend Function Declarations
In the following example, the addBudget function of class AuxilliaryOffice has been declared a friend in the Budget class The auxiliary office (perhaps in another country) makes a separate budget request which must be added to the overall corporate budget The friend declaration tells the compiler that the function is to be granted access to Budget’s private members In Auxil.h there is a forward declaration of the Budget class This tells the compiler that a class named Budget will be declared later in the program. This is needed because the compiler will process Auxil.h before it processes the Budget class declaration C++: Classes & Objects -2

30 Budget.h version 3 #ifndef BUDGET_H #define BUDGET_H #include "Auxil.h" // Budget class declaration class Budget { private: static double corpBudget; // Static member variable double divisionBudget; // Instance member variable public: Budget() { divisionBudget = 0; } void addBudget(double b) { divisionBudget += b; corpBudget += b; } double getDivisionBudget() const { return divisionBudget; } double getCorpBudget() const { return corpBudget; } // Static member function static void mainOffice(double); // Friend function friend void AuxiliaryOffice::addBudget(double, Budget &); }; #endif C++: Classes & Objects -2

31 Budget.cpp version 3 #include "Budget.h" double Budget::corpBudget = 0; // Definition of static member variable //********************************************************** // Definition of static member function mainOffice. * // This function adds the main office's budget request to * // the corpBudget variable. * void Budget::mainOffice(double moffice) { corpBudget += moffice; } C++: Classes & Objects -2

32 Auxil.h Auxil.cpp #ifndef AUXIL_H #define AUXIL_H // Forward declaration of Budget class class Budget; // Aux class declaration class AuxiliaryOffice { private: double auxBudget; public: AuxiliaryOffice() { auxBudget = 0; } double getDivisionBudget() const { return auxBudget; } void addBudget(double, Budget &); }; #endif #include "Auxil.h" #include "Budget.h" //********************************************************* // Definition of member function mainOffice. // This function is declared a friend by the Budget class. // It adds the value of argument b to the static corpBudget // member variable of the Budget class. void AuxiliaryOffice::addBudget(double b, Budget &div) { auxBudget += b; div.corpBudget += b; } C++: Classes & Objects -2

33 Main.cpp part 1 #include <iostream> #include <iomanip>
#include "Budget.h" using namespace std; int main() { int count; // Loop counter double mainOfficeRequest; // Main office budget request const int NUM_DIVISIONS = 4; // Number of divisions // Get the main office's budget request. cout << "Enter the main office's budget request: "; cin >> mainOfficeRequest; Budget::mainOffice(mainOfficeRequest); Budget divisions[NUM_DIVISIONS]; // Array of Budget objects. AuxiliaryOffice auxOffices[4]; // Array of AuxiliaryOffice // Get the budget requests for each division and their auxiliary offices. for (count = 0; count < NUM_DIVISIONS; count++) double budgetAmount; // To hold input // Get the request for the division office. cout << "Enter the budget request for division "; cout << (count + 1) << ": "; cin >> budgetAmount; divisions[count].addBudget(budgetAmount); C++: Classes & Objects -2

34 Main.cpp part 2 // Get the request for the auxiliary office. cout << "Enter the budget request for that division's\n"; cout << "auxiliary office: "; cin >> budgetAmount; auxOffices[count].addBudget(budgetAmount, divisions[count]); } // Display the budget requests and the corporate budget. cout << fixed << showpoint << setprecision(2); cout << "\nHere are the division budget requests:\n"; for (count = 0; count < NUM_DIVISIONS; count++) { cout << "\tDivision " << (count + 1) << "\t\t$"; cout << divisions[count].getDivisionBudget() << endl; cout << "\tAuxiliary office:\t$"; cout << auxOffices[count].getDivisionBudget() << endl << endl; cout << "Total Budget Requests:\t$ "; cout << divisions[0].getCorpBudget() << endl; return 0; C++: Classes & Objects -2

35 Friend Class Declaration
An entire class can be declared a friend of a class: class aClass {private: int x; friend class frClass; }; class frClass {public: void fSet(aClass &c,int a){c.x = a;} int fGet(aClass c){return c.x;}

36 Friend Class Declaration
If frClass is a friend of aClass, then all member functions of frClass have unrestricted access to all members of aClass, including the private members. The Budget class could make the Auxilliary Office class its friend by declaring friend class AuxilliaryOffice; In general, restrict the property of Friendship to only those functions that must have access to the private members of a class.

37 11.4 Memberwise Assignment
Can use = to assign one object to another, or to initialize an object with an object’s data Examples (assuming class V): V v1, v2; . // statements that assign . // values to members of v1 v2 = v1; // assignment means: copy all member values from v1 and assign to the corresponding member variables of v2 V v3 = v2; // initialization See pr11-05.cpp

38 11.5 Copy Constructors Special constructor used when a newly created object is initialized to the data of another object of same class Default copy constructor copies field-to-field Default copy constructor works fine in many cases See pr11-06.cpp

39 C++: Classes & Objects -2

40 C++: Classes & Objects -2

41 Copy Constructors Special constructor used when a newly created object is initialized to the data of another object of same class Default copy constructor copies field-to-field Default copy constructor works fine in many cases C++: Classes & Objects -2

42 Copy Constructors Problem: what if object contains a pointer?
#include <cstring> class PersonInfo { private: char *name; int age; public: PersonInfo(char *n, int a) { name = new char[strlen(n) + 1]; strcpy(name, n); age = a; } ~PersonInfo() { delete [] name; } const char *getName() { return name; } int getAge() { return age; } }; C++: Classes & Objects -2

43 Copy Constructors A potential problem with this class lies with the pointer member The constructor dynamically allocates a section of memory and copies a string to it PersonInfo person1(“John Smith”,30); If we perform the assignment PersonInfo person2 = person1; person2’s constructor is not called so a separate section of memory is not allocated for person2’s name member C++: Classes & Objects -2

44 Dynamically allocated memory
Copy Constructors Both pointers will point to the same address If either of the two objects change the string, it will be reflected in both objects If one object is destroyed, the remaining object’s pointer will still reference this section of memory although it should no longer be used Dynamically allocated memory pointer1’s name pointer John Smith pointer2’s name pointer C++: Classes & Objects -2

45 Copy Constructors If you include a method in the class
void setName(char *n){strcpy(name, n); } and then include person1.setName(“Ira R”); in the main program, both objects will again have the same name if you invoke the function getName() for person1 and person2 C++: Classes & Objects -2

46 Copy Constructors What we really want is to create a copy of the dynamically allocated memory and have person2’s pointer point to it This is accomplished by using a copy constructor For original object PersonInfo(char *n, int a) { name = new char[strlen(n) + 1]; strcpy(name, n); age = a; } For copy object PersonInfo(PersonInfo & obj) { name = new char[strlen(obj.name) + 1]; strcpy(name, obj.name); age = obj.age;

47 Copy Constructors When the assignment operator is used to initialize person2 with the contents of person1, person1’s object is passed as an argument to person2’s object’s copy constructor Takes a reference parameter to another object of the same class

48 Copy Constructors PersonInfo(const PersonInfo & obj)
Because copy constructor's are required to use reference parameters, they have access to their argument’s data Since the purpose of the copy constructor is to make a copy of the argument, there is no reason the constructor should modify the argument’s data Thus, it is a good idea to specify the keyword const in the parameter list PersonInfo(const PersonInfo & obj)

49 Programmer-Defined Copy Constructors
The copy constructor avoids problems caused by memory sharing Can allocate separate memory to hold new object’s dynamic member data Can make new object’s pointer point to this memory Copies the data, not the pointer, from the original object to the new object See pr11-08.cpp, NumberArray2.h, and NumberArray2.cpp

50 Copy Constructor Example
class CpClass { int *p; public: CpClass(const CpClass &obj) { p = new int; *p = *obj.p; } CpClass(int v=0) { p = new int; *p = v; } ~CpClass(){delete p;} };

51 11.6 Operator Overloading Operators such as =, +, and others can be redefined for use with objects of a class The name of the function for the overloaded operator is operator followed by the operator symbol, e.g., operator+ is the overloaded + operator and operator= is the overloaded = operator

52 Operator Overloading - friend functions Operators can be overloaded as
- instance member functions or as - friend functions Prototype for the overloaded operator goes in the declaration of the class that is overloading it Overloaded operator must have the same number of parameters as the standard version. For example, operator= must have two parameters, since the standard = operator takes two parameters.

53 Operator Overloading void operator=(const SomeClass &rval) Prototype:
Operator is called via object on left side parameter for object on right side of operator return type function name C++: Classes & Objects -2

54 Operator Function Overloading
#include <cstring> class PersonInfo { private: char *name; int age; public: // Constructor PersonInfo(char *n, int a) { name = new char[strlen(n) + 1]; strcpy(name, n); age = a; } // Copy Constructor PersonInfo(const PersonInfo &obj) { name = new char[strlen(obj.name) + 1]; strcpy(name, obj.name); age = obj.age; } // Destructor ~PersonInfo() { delete [] name; } // Accessor functions const char *getName() { return name; } int getAge() { return age; } // Overloaded = operator void operator=(const PersonInfo &right) { delete [] name; name = new char[strlen(right.name)+1]; strcpy(name, right.name); age = right.age; } }; Because the operator function is a member of the PersonInfo class, the function will be executed only when the object on the left side is of the class C++: Classes & Objects -2

55 Invoking an Overloaded Operator
Operator can be invoked as a member function: object1.operator=(object2); person2.operator=(person1); It can also be used in more conventional manner: object1 = object2; person2 = person1; Run PersonInfoOverloadObject project C++: Classes & Objects -2

56 Invoking an Overloaded Operator
// Create and initialize the jim object. PersonInfo jim("Jim Young", 27); // Create and initialize the bob object. PersonInfo bob("Bob Faraday", 32); // Create the clone object and initialize with jim. PersonInfo clone = jim; // Assign bob to clone. //Now the clone will change to bob and bob will change to jim clone = bob; // Call overloaded = operator bob = jim; // Call overloaded = operator The jim Object contains: Jim Young, 27 The bob Object contains: Bob Faraday, 32 The clone Object contains: Jim Young, 27 Now the clone will change to bob and bob will change to jim. The bob Object contains: Jim Young, 27 The clone Object contains: Bob Faraday, 32 C++: Classes & Objects -2

57 = Operator’s Return Value
Return type the same as the left operand; supports notation like: object1 = object2 = object3; a=b=c; The expression b=c causes c to be assigned to b and then returns the value of c. The return value is stored in a. This requires the object’s overloaded = operator to have a valid return type Function declared as follows: const SomeClass operator=(const someClass &rval) const PersonInfo operator=(const PersonInfo & right) In function, include as last statement: return *this; which returns the value of a dereferenced pointer this C++: Classes & Objects -2

58 = Operator’s Return Value
// Create and initialize the jim object. PersonInfo jim("Jim Young", 27); // Create and initialize the bob object. PersonInfo bob("Bob Faraday", 32); // Create the clone object and initialize with jim. PersonInfo clone = jim; // Assign jim to bob and clone. clone = bob = jim; // Call overloaded = operator The jim Object contains: Jim Young, 27 The bob Object contains: Jim Young, 27 The clone Object contains: Jim Young, 27 C++: Classes & Objects -2

59 Overloading Operators as Instance Members
#ifndef _LENGTH_H #define _LENGTH_H #include <iostream> using namespace std; class Length { private: int len_inches; public: Length(int feet, int inches) { setLength(feet, inches); } Length(int inches){ len_inches = inches; } int getFeet(){ return len_inches / 12; } int getInches() { return len_inches % 12; } void setLength(int feet, int inches){ len_inches= 12*feet+inches; } friend Length operator+(Length a, Length b); friend Length operator-(Length a, Length b); friend bool operator< (Length a, Length b); friend bool operator== (Length a, Length b);}; #endif See pr11-09.cpp, overload.h, and overload.cpp

60 Overloading Operators as Instance Members
#include "Length.h“ Length operator+(Length a, Length b) {return Length(a.len_inches + b.len_inches);} Length operator-(Length a, Length b) { return Length(a.len_inches - b.len_inches);} bool operator==(Length a, Length b) { return a.len_inches == b.len_inches; } bool operator<(Length a, Length b) { return a.len_inches < b.len_inches; } see Project Length-Overloaded See pr11-09.cpp, overload.h, and overload.cpp

61 Notes on Overloaded Operators
Can change the entire meaning of an operator Most operators can be overloaded Cannot change the number of operands of the operator 1. = symbol is always a binary operator 2. ++ and -- are unary operator Cannot overload the following operators: ?: . .* :: sizeof

62 Overloading + and - Operators
You have a class FeetInches that allows you to enter a measurement in feet and inches You want to be able to add and subtract two objects of the class and get a result in feet and inches 6 feet 10 inches + 3 feet 8 inches  feet 18inches10 feet 6 inches 6 feet 4 inches – 3 feet 10 inches  feet (-6) inches2 feet 6 inches Want operator functions to allow this type of non standard addition and subtraction C++: Classes & Objects -2

63 FeetInches.h C++: Classes & Objects -2
#ifndef FEETINCHES_H #define FEETINCHES_H // The FeetInches class holds distances or measurements // expressed in feet and inches. class FeetInches { private: int feet; // To hold a number of feet int inches; // To hold a number of inches void simplify(); // Defined in FeetInches.cpp public: FeetInches(int f = 0, int i = 0) { feet = f; inches = i; simplify(); } void setFeet(int f) { feet = f; } void setInches(int i) { inches = i; simplify(); } int getFeet() const { return feet; } int getInches() const { return inches; } FeetInches operator + (const FeetInches &); // Overloaded + FeetInches operator - (const FeetInches &); // Overloaded - }; #endif C++: Classes & Objects -2

64 FeetInches.cpp C++: Classes & Objects -2
// Implementation file for the FeetInches class #include <cstdlib> // Needed for abs() #include "FeetInches.h" void FeetInches::simplify() { if (inches >= 12) feet += (inches / 12); inches = inches % 12; } else if (inches < 0) feet -= ((abs(inches) / 12) + 1); inches = 12 - (abs(inches) % 12); //********************************************** // Overloaded binary + operator. * FeetInches FeetInches::operator + (const FeetInches &right) FeetInches temp; temp.inches = inches + right.inches; temp.feet = feet + right.feet; temp.simplify(); return temp; //********************************************** // Overloaded binary - operator * FeetInches FeetInches::operator -(const FeetInches &right) { FeetInches temp; temp.inches = inches - right.inches; temp.feet = feet - right.feet; temp.simplify(); return temp; } C++: Classes & Objects -2

65 FeetInchesMain.cpp PROGRAM OUTPUT
int feet, inches; FeetInches first, second, third; // Get a distance from the user. cout << "Enter a distance in feet and inches: "; cin >> feet >> inches; // Store the distance in the first object. first.setFeet(feet); first.setInches(inches); // Get another distance from the user. cout << "Enter another distance in feet and inches: "; // Store the distance in second. second.setFeet(feet); second.setInches(inches); // Assign first + second to third. third = first + second; // Display the result. cout << "first + second = "; cout << third.getFeet() << " feet, "; cout << third.getInches() << " inches.\n"; // Assign first - second to third. third = first - second; cout << "first - second = "; PROGRAM OUTPUT Enter a distance in feet and inches: 6 10 Enter another distance in feet and inches: 3 8 first + second = 10 feet, 6 inches. first - second = 3 feet, 2 inches. C++: Classes & Objects -2

66 Overloading >, < and == operators
Now I’d like to compare to FeetInches objects to determine if one is less than another, greater than another or if the two are equal First, what rule should we use to compare to FeetInches objects Assuming that both objects have been “simplified”, compare the feet value of both objects. If the feet are equal, then compare the inches value C++: Classes & Objects -2

67 Overloading >, < and == operators
Include these statements in FeetInches.h bool operator > (const FeetInches &); // Overloaded > bool operator < (const FeetInches &); // Overloaded < bool operator == (const FeetInches &); // Overloaded == Include these functions in FeetInches.cpp bool FeetInches::operator > (const FeetInches &right) { bool status; if (feet > right.feet) status = true; else if (feet == right.feet && inches > right.inches) status = true; else status = false; return status; } bool FeetInches::operator < (const FeetInches &right) if (feet < right.feet) status = true; else if (feet == right.feet && inches < right.inches) status = true; bool FeetInches::operator == (const FeetInches &right) if (feet == right.feet && inches == right.inches) status = true; C++: Classes & Objects -2

68 Overloading >, < and == operators
Instantiate two FeetInches objects and compare them int feet, inches; FeetInches first, second; cout << "Enter a distance in feet and inches: "; cin >> feet >> inches; first.setFeet(feet); first.setInches(inches); cout << "Enter another distance in feet and inches: "; second.setFeet(feet); second.setInches(inches); // Compare the two objects. if (first == second) cout << "first is equal to second.\n"; if (first > second) cout << "first is greater than second.\n"; if (first < second) cout << "first is less than second.\n"; Enter a distance in feet and inches: 6 10 Enter another distance in feet and inches: 5 3 first is greater than second. Enter another distance in feet and inches: 6 11 first is less than second. Enter a distance in feet and inches: 6 6 Enter another distance in feet and inches: 6 6 first is equal to second. C++: Classes & Objects -2

69 Overloading Types of Operators
++, -- operators overloaded differently for prefix vs. postfix notation Overloaded relational operators should return a bool value Overloaded stream operators >>, << must return istream, ostream objects and take istream, ostream objects as parameters See project Length1-Overloaded See Length1.h, Length1.cpp, pr11-11.cpp for the first three

70 Overloaded [] Operator
The string class overload the [ ] operator so you can access the individual characters stored in string class objects Can be used to create classes that behave like arrays, providing bounds-checking on subscripts Overloaded [] returns a reference to object, not an object itself This is because the statement table[5]=27; must be possible The = operator requires the object on its left to be an lvalue (a memory location whose contents may be changed A reference to an integer (but not an integer itself) is an lvalue Thus table[5]=27; is equivalent to *(aptr+5) = 27; See project IntArray bulletsSee pr11-12.cpp for the string class’s overloaded [ ] operator; See intarray.h, intarray.cpp, pr11-13.cpp for these bullets

71 11.7 Type Conversion Operators
Conversion Operators are member functions that tell the compiler how to convert an object of the class type to a value of another type The conversion information provided by the conversion operators is automatically used by the compiler in assignments, initializations, and parameter passing

72 Syntax of Conversion Operators
Conversion operator must be a member function of the class you are converting from The name of the operator is the name of the type you are converting to The operator does not specify a return type, the return type is inferred from the name of the operator function Because the function is a member function, it operates on the calling object and requires no parameters

73 Object Conversion Type of an object can be converted to another type
Automatically done for built-in data types Must write an operator function to perform conversion To convert a FeetInches object to a double: FeetInches::operator double() {double temp=feet; temp+=(inches/12.0); return temp;} To convert a FeetInches object to an int: FeetInches::operator int() {return feet;} //drops the inches Assuming distance is a FeetInches object, allows statements like: int d = distance; C++: Classes & Objects -2

74 11.8 Convert Constructors Convert constructors are constructors with a single parameter of a type other than the class They provide a way for the compile to convert a value of a given type to an object of the class Also provides the compiler with a way of performing implicit type conversions –done when the value of the constrcutor’s parameter type is given where a value of the class type is expected Since the constructor IntClass(int) takes a single parameter if a type other than IntClass, it is a convert constructor class IntClass{ private: int value; public: IntClass(int intValue) {value = intValue;} int getValue(){return value;) } See Convert.h, Convert.cpp, and pr11-16.cpp

75 Convert Constructors Are automatically invoked whenever the context demands a class object but a value of constructor’s parameter type is provided 1. An object of the class is initialzed with a value of the convert constructor’s parameter type IntClass intObject = 23; 2. An object of the class is assigned a value of the convert constructor’s parameter type intObject = 24; 3. A function expecting a value parameter of the class type is instead passed a value of the constructor’s parameter type void printValue (IntClass x){ cout<< x.getValue(); } and then pass it an int when we call it printValue(25); The compiler will use the convert constructor to convert the integer 25 into an object of the IntClass class and will then pass the object to the function. Convert constructors are only invoked when the formal parameter uses pass by value See Convert.h, Convert.cpp, and pr11-16.cpp

76 Convert Constructors 4. A function that declares a return type of the class type actually returns a value of the convert constructor’s parameter type IntClass f (int intValue) { return intValue;} Note that the function returns a value of type integer even though IntClass is declared as its return type. Again, the compiler will implicitly call the convert constructor ro convert the integer intValue to an IntClass object. This object is returned from the function See project Convert See Convert.h, Convert.cpp, and pr11-16.cpp

77 Example of a Convert Constructor
The C++ string class has a convert constructor that converts from C-strings: class string { public: string(char *); //convert }; This allows programmers to pass C-strings to functions that expect string object parameters, assign C-strings to string objects and use C-strings as initial values of string objects

78 Uses of Convert Constructors
Automatically invoked by the compiler to create an object from the value passed as parameter: string s("hello"); //convert C-string Compiler allows convert constructor to be invoked with assignment-like notation: string s = "hello"; //convert C-string

79 11.9 Aggregation and Composition
Class aggregation: An object of one class owns an object of another class Class composition: A form of aggregation where the enclosing class controls the lifetime of the objects of the enclosed class Supports the modeling of ‘has-a’ relationship between classes – enclosing class ‘has a(n)’ instance of the enclosed class See pr11-17.cpp

80 Object Composition class StudentInfo { private: string firstName, LastName; string address, city, state, zip; ... }; class Student StudentInfo personalData;

81 Member Initialization Lists
Used in constructors for classes involved in aggregation. Member Initialization lists can be used to simplify the coding of constructors Allows constructor for enclosing class to pass arguments to the constructor of the enclosed class Notation: owner_class(parameters):owned_class(parameters);

82 class Date { private: string month; int day; int year; public: Date(string m, int d, int y) { month = m; day = d; year = y; } }; class Person { string name; Date dateOfBirth; Person(string name, string month, int day, int year): dateOfBirth(month, day, year) { this->name = name;}

83 The code on the previous slide can be written as: class Date { private: string month; int day; int year; public: Date(string m, int d, int y): month(m), day(d), year(y) {// body is empty due to initialization lists } }; class Person { string name; Date dateOfBirth; Person(string name, string month, int day, int year): name(name), dateOfBirth(month, day, year) { //body is empty due to initialization lists }

84 Member Initialization Lists
List the members of the initialization list in the same order that they are declared in the class The compiler is able to determine that the first occurrence of name in name(name) refers to the member variable and the second to the parameter

85 Aggregation Through Pointers
A ‘has-a’ relationship can be implemented by owning a pointer to an object Can be used when multiple objects of a class may ‘have’ the same attribute for a member ex: each person has a country of residence and each country has a name and other attributes Using pointers minimizes data duplication and saves space

86 Aggregation Through Pointers
class Country { string name; // additional fields }; class Person{ string name; Date dateOfBirth; Country *pCountry public: Person(string name, string month, int day, int year, Country *pC): dateOfBirth(month,day,year),name(name),pCountry(pC) { }

87 Aggregation, Composition, and Object Lifetimes
Aggregation represents the owner/owned relationship between objects. Composition is a form of aggregation in which the lifetime of the owned object is the same as that of the owner object Owned object is usually created as part of the owning object’s constructor, destroyed as part of owning object’s destructor

88 Examples of Composition
Class C contains a member that is an object of another class D The contained D object is created at the same time that the C object is created and is destroyed when the containing C object is destroyed Another example is when a class C contains a pointer to a D object and the D object is created by the C constructor and destroyed by the C constructor

89 Aggregation,Composition, Object Lifetimes
class Date { private: string month; int day; int year; int personID; //ID of person whose birthday this is public: Date(string m, int d, int y, int id): month(m), day(d), year(y),personID(id) {cout<<"Date-Of-Birth object for person " <<personID<< " has been created.\n"; } ~Date() <<personID<< " has been destroyed.\n"; };

90 Aggregation,Composition, Object Lifetimes
class Country { string name; public: Country(string name):name(name) { cout<<"A country object has been created.\n"; } ~Country() cout<<"A country object has been destroyed.\n"; };

91 Aggregation,Composition, Object Lifetimes
class Person{ string name; Date dateOfBirth; int personID; Country *pCountry; public: Person(string name, string month, int day, int year, Country *pC): name(name), dateOfBirth(month,day,year,Person::uniquePersonID), personID(Person::uniquePersonID), pCountry(pC) { cout<<"Person object"<<personID<<" has been created.\n"; Person::uniquePersonID++; } ~Person() {cout<<"Person object"<<personID<<" has been destroyed.\n“; } static int uniquePersonID; }; int Person::uniquePersonID=1;

92 Aggregation,Composition, Object Lifetimes
The relationship between the dateOfBirth objects and the Person objects that contain them is an example of composition Those Date objects are created at the same time, and die at the same time, as the Person objects that own them Aggregation in its more general form is exemplified by the has-a relationship between Person and Country

93 Inheritance Inheritance is a way of creating a new class by starting with an existing class and adding new members The new class can replace or extend the functionality of the existing class Inheritance models the 'is-a' relationship between classes A poodle is a dog A rectangle is a shape A square is a rectangle is a shape

94 Inheritance - Terminology
The existing class is called the base class Alternates: parent class, superclass The new class is called the derived class Alternates: child class, subclass

95 Inheritance Syntax and Notation
Inheritance Class Diagram // Existing class class Base { }; // Derived class class Derived : public Base Base Class Derived Class See pr11-18.cpp and inheritance.h

96 Inheritance of Members
class Parent { int a; void bf(); }; class Child : public Parent int c; void df(); Objects of Parent have members int a; void bf(); Objects of Child have members int c; void df();

97 Inheritance of Members
class Person { private: string name; public: Person() { setName(""); } Person(string pName) { setName(pName); } void setName(string pName) { name = pName; } string getName() { return name; } }; class Student:public Person private: Discipline major; Person *advisor; void setMajor(Discipline d) { major = d; } Discipline getMajor() { return major; } void setAdvisor(Person *p) { advisor = p; } Person *getAdvisor() { return advisor; }

98 Inheritance of Members
class Faculty:public Person { private: Discipline department; public: void setDepartment(Discipline d) { department = d; } Discipline getDepartment( ) { return department; } }; Project Inheritance

99 11.11 Protected Members and Class Access
protected member access specification: A class member labeled protected is accessible to member functions of derived classes as well as to member functions of the same class Like private, except accessible to members functions of derived classes See inheritance1.h, inheritance1.cpp, pr11-19.cpp

100 Protected Members and Class Access
Change project Inheritance code to add to the Faculty class a constructor that takes as parameter the name and dept of the professor The constructor should call the setName() function inherited from the Person class Instead change the access specification of the name field of Person to protected and have the faculty constructor access it directly Member functions of a base class can be declared protected – they can be called by member functions of derived classes and by friend functions and friend classes See inheritance1.h, inheritance1.cpp, pr11-19.cpp

101 Base Class Access Specification
Base class access specification: determines how private, protected, and public members of base class can be accessed by derived classes

102 Base Class Access - public inheritance
C++ supports three inheritance modes, also called base class access modes: - public inheritance class Child : public Parent { }; - protected inheritance class Child : protected Parent{ }; - private inheritance class Child : private Parent{ };

103 Base Class Access vs. Member Access Specification
Base class access not same as member access specification: Base class access: determine access for inherited members Member access specification: determine access for members defined in the class

104 Member Access Specification
Specified using the keywords private, protected, public class MyClass { private: int a; protected: int b; void fun(); public: void fun2(); };

105 Base Class Access Specification
class Child : public Parent { protected: int a; public: Child(); }; base access member access

106 Base Class Access Specifiers
public – object of derived class can be treated as object of base class (not vice-versa) protected – more restrictive than public, but allows derived classes to know some of the details of parents private – prevents objects of derived class from being treated as objects of base class.

107

108 appear in derived class
Effect of Base Access How base class members appear in derived class Base class members private: x protected: y public: z private base class x inaccessible private: y private: z protected base class private: x protected: y public: z x inaccessible protected: y protected: z public base class private: x protected: y public: z x inaccessible protected: y public: z

109 More Inheritance vs. Access
private members: char letter; float score; void calcGrade(); public members: void setScore(float); float getScore(); char getLetter(); class Grade int numQuestions; float pointsEach; int numMissed; Test(int, int); class Test : public Grade When Test class inherits from Grade class using public class access, it looks like this: int numQuestions: float getLetter(); Inheritance & Polymorphism

110 More Inheritance vs. Access
private members: char letter; float score; void calcGrade(); public members: void setScore(float); float getScore(); char getLetter(); class Grade int numQuestions; float pointsEach; int numMissed; Test(int, int); When Test class inherits from Grade class using protected class access, it looks like this: int numQuestions: protected members: float getLetter(); class Test : protected Grade Inheritance & Polymorphism

111 More Inheritance vs. Access
private members: int numQuestions: float pointsEach; int numMissed; void setScore(float); float getScore(); float getLetter(); public members: Test(int, int); char letter; float score; void calcGrade(); char getLetter(); class Grade int numQuestions; When Test class inherits from Grade class using private class access, it looks like this: class Test : private Grade Inheritance & Polymorphism

112 class Base{ private: int x; protected: int y; public: int z; public: int getX(){return x;}int getY(){return y;} int getZ(){return z;} Base(int a, int b, int c){x=a; y=b; z=c; cout<<"In Base;cout<<" x "<<x; cout<<" y "<<y; cout<<" z "<<z;}} Base(){} }; class Derived: <base access> Base{ private: int w; public: Derived(int a, int b, int c):Base(a, b, c){ cout<<"x "<<x; cout<<"y "<<y; cout<<" z "<<z; cout<<" getX "<<getX()<<endl; } int main() { Derived d(10, 20,30); cout<<"In main\n"; cout<<"x "<<d.x; cout<<"y "<<d.y; cout<<" z "<<d.z; cout<<" getX "<<d.getX()<<endl; return 0;

113 Output results After you instantiate object Derived d in main the Derived class attempts to print x, y and z directly and invoke getX() in Derived class and main Derived: public Base Derived – y, z, getX() Main – z, getX() Derived: protected Base Main – nothing Derived: private Base Within Base - x, y, and z are always directly accessible

114 11.12 Constructors,Destructors and Inheritance
By inheriting every member of the base class, a derived class object contains a base class object The derived class constructor can specify which base class constructor should be used to initialize the base class object

115 Order of Execution When an object of a derived class is created, the base class’s constructor is executed first, followed by the derived class’s constructor When an object of a derived class is destroyed, its destructor is called first, then that of the base class project BaseDerivedOrderExecution See pr11-20.cpp

116 Order of Execution int main() { UnderGrad u1; ... return 0;
// Student – base class // UnderGrad – derived class // Both have constructors, destructors int main() { UnderGrad u1; ... return 0; }// end main Execute Student constructor, then execute UnderGrad constructor Execute UnderGrad destructor, then execute Student destructor

117 Passing Arguments to Base Class Constructor
Allows selection between multiple base class constructors Specify arguments to base constructor on derived constructor heading Can also be done with inline constructors Must be done if base class has no default constructor

118 Passing Arguments to Base Class Constructor
class Parent { int x, y; public: Parent(int,int); }; class Child : public Parent { int z public: Child(int a): Parent(a,a*a) {z = a;} See inheritance2.h, inheritance2.cpp, pr11-21App.cpp

119 Passing Arguments to Base Class Constructor
Faculty(string fname, Discipline d) { name = fname; department=d; } now becomes Faculty(string fname, Discipline d): Person(fname) { department=d; } The arguments to the base class constructor must be specified in the definition of the derived class constructor and not in its declaration Student (string sname, Discipline d, Person *adv); in inheritance2.h is the declaration Student::Student(string sname, Discipline d, Person *adv):Person(sname) {major=d; advisor = adv;} in inheritance2.cpp is the definition See inheritance2.h, inheritance2.cpp, pr11-21App.cpp

120 WHAT IS THE OUTPUT OF THIS PROGRAM?
#include <iostream> using namespace std; class Base { public : Base(){cout<<"Entering the base\n";} Base(char *str){cout<<"This base is "<<str<<"\n";} ~Base (){cout<<"Leaving the base\n";} }; class Camp:public Base { public: Camp(){cout<<"Entering the camp\n";} Camp(char * str1, char *str2):Base(str1) {cout<<"The camp is "<<str2<<"\n";} ~Camp (){cout<<"Leaving the camp\n";} int main() { Camp outpost("secure", "secluded"); return 0; } WHAT IS THE OUTPUT OF THIS PROGRAM?

121 11.13 Overriding Base Class Functions
Overriding: function in a derived class that has the same name and parameter list as a function in the base class A derived class can override a member function of its base class by defining a derived class member function with the same name and parameter list Typically used to replace a function in base class with different actions in derived class Not the same as overloading – with overloading, the parameter lists must be different See inheritance3.h, inheritance3.cpp, pr11-21.cpp

122 Access to Overridden Function
When a function is overridden, all objects of derived class use the overriding function. If necessary to access the overridden version of the function, it can be done using the scope resolution operator with the name of the base class and the name of the function: Student::getName();

123 Getting in “Shape” Base class Shape has an instance variable area and functions getArea and setArea Derived class Circle has it’s own instance variable radius and functions getRadius and setRadius Note that setRadius calls function setArea and passes the area of the circle using the formula π*r2 This sets the value of area in the base class. Since it is private , Circle can access it only via the public functions Project ShapeInheritance Inheritance & Polymorphism

124 Getting in “Shape” class Shape{ private: double area; public:
void setArea(double a) {area = a;} double getArea() {return area;} }; class Circle: public Shape { double radius; void setRadius(double r){ radius = r; setArea(3.14*r*r); } double getRadius() {return radius;} Inheritance & Polymorphism

125 Getting in “Shape” #include <iostream> #include "Circle.h" using namespace std; int main() { Circle c; c.setRadius(10.0); cout<<"Area of the circle is "<<c.getArea()<<endl; return 0; } Area of the circle is 314 Instantiate an object of the Circle class; this automatically instantiates an object of the Shape class Call the setRadius function – this calls the setArea function of the Shape class which sets the private instance variable area of the Shape class Inheritance & Polymorphism

126 Getting in “Shape” Create an new class named Rectangle. It has
private instance variables length and width of type double public functions getLength, getWidth and setLengthAndWidth setLengthAndWidth calls setArea with the value length*width Add code to the main program to instantiate a Rectangle object r, set the length to 6 and width to 9 and then call the getArea function on r Inheritance & Polymorphism

127 Getting in “Shape” class Rectangle: public Shape { private:
double length; double width; public: void setLengthAndWidth(double l, double w){ length = l; width = w; setArea(length*width); } double getLength() {return length;} double getWidth() {return width;} }; Inheritance & Polymorphism

128 Getting in “Shape” #include <iostream> #include "Circle.h"
#include "Rectangle.h" using namespace std; int main() { Circle c; c.setRadius(10.0); cout<<"Area of the circle is "<<c.getArea()<<endl; Rectangle r; r.setLengthAndWidth(6,9); cout<<"Area of the rectangle is "<<r.getArea()<<endl; return 0; } Area of the circle is 314 Area of the rectangle is 54 Inheritance & Polymorphism

129 Problem with Redefining
Consider this situation: Class BaseClass defines functions x() and y(). x() calls y(). Class DerivedClass inherits from BaseClass and redefines function y(). An object D of class DerivedClass is created and function x() is called. When x() is called, which y() is used, the one defined in BaseClass or the the redefined one in DerivedClass? Inheritance & Polymorphism

130 Problem with Redefining
BaseClass void X(); void Y(); Object D invokes function X()in BaseClass. function X()invokes function Y() in BaseClass, not function Y()in DerivedClass, because function calls are bound at compile time. This is static binding. DerivedClass void Y(); DerivedClass D; D.X(); Inheritance & Polymorphism

131 Chapter 11: More About Classes and Object-Oriented Programming
Starting Out with C++ Early Objects Seventh Edition by Tony Gaddis, Judy Walters, and Godfrey Muganda


Download ppt "Chapter 11: More About Classes and Object-Oriented Programming"

Similar presentations


Ads by Google