Transcript PowerPoint Slides for Starting Out with C++ Early Objects
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
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 11-2
Topics
(continued) 11.8 Convert Constructors 11.9 Aggregation and Composition 11.10 Inheritance 11.11 Protected Members and Class Access 11.12 Constructors, Destructors, and Inheritance 11.13 Overriding Base Class Functions 11-3
11.1 The
this
Pointer and Constant Member Functions
this
pointer: - 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 11-4
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; }
11-5
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.
11-6
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 11-7
1)
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; };
11-8
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;
11-9
static member variable
Contents of Tree.
h
1 // Tree class 2 class Tree 3 { Static member declared here.
4 private: 5
static int objectCount;
6 public: // Static member variable.
7 // Constructor 8 Tree() 9 { objectCount++; } 10 11 // Accessor function for objectCount 12 int getObjectCount() const 13 { return objectCount; } 14 }; 15 Static member defined here.
16 // Definition of the static member variable, written 17 // outside the class.
18
int Tree::objectCount = 0;
C++: Classes & Objects -2 10
C++: Classes & Objects -2 11
Three Instances of the Tree Class, Only One objectCount Variable
C++: Classes & Objects -2 12
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; val1 valCount 2 val2
11-13
Static Member Functions
1)Declared with
static
before return type:
class IntVal { public: static private: int getValCount() { return valCount; } int value; static int valCount; };
11-14
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
used pointer cannot be 4) Can be called before any objects of the class have been created 5) Used mostly to manipulate static member variables of the class 11-15
Modified Version of Tree.
h
1 // Tree class 2 class Tree 3 { 4 private: 5 static int objectCount; // Static member variable.
6 public: 7 // Constructor 8 Tree() 9 { objectCount++; } 10 11 // Accessor function for objectCount 12
static
int getObjectCount() 13 { return objectCount; } 14 }; 15 16 // 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 16
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 17
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
const static
and could not be C++: Classes & Objects -2 18
Budget version 1
#ifndef BUDGET_H #define BUDGET_H class Budget { private: static double corpBudget; double divisionBudget; // Instance member public: Budget() { divisionBudget = 0; } // Static member 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 19
Budget
#include
version 1
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"; 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 20
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 21
Budget
#ifndef BUDGET_H #define BUDGET_H
version 2
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); #endif // Static member function
C++: Classes & Objects -2 22
version 2
#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 23
Budget
#include
version 2
// Display corporate and division budgets int main() { int count; // Main office budget request double mainOfficeRequest; const int NUM_DIVISIONS = 4;// # of divisions cout << fixed << showpoint<< setprecision(2); cout << "\nHere are the division budget requests:\n"; for (count=0; count
//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); }
C++: Classes & Objects -2 24
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()
to
{ return mainOffice; } Budget.h
C++: Classes & Objects -2 25
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 it access
friend
keyword in the function prototype of the class granting 11-26
Friend Function Declarations
1) 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; }
11-27
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; } };
11-28
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
class there is a forward declaration of the Budget This tells the compiler that a class named declared later in the program. This is needed because the compiler will process Auxil.h
Budget will be before it processes the Budget class declaration C++: Classes & Objects -2 29
Budget.h
#ifndef BUDGET_H #define BUDGET_H #include "Auxil.h"
version 3
// 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 30
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 31
Auxil.h
#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; }
Auxil.cpp
#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; } }; void addBudget(double, Budget &); #endif
C++: Classes & Objects -2 32
Main.cpp part 1
#include
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 33
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 34
Friend Class Declaration
3) 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;} };
11-35
Friend Class Declaration
If
frClass
of
frClass
is a friend of
aClass
, then all member functions 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.
11-36
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 corresponding member variables of v2 and assign to the
V v3 = v2; // initialization
11-37
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 11-38
C++: Classes & Objects -2 39
C++: Classes & Objects -2 40
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 41
Copy Constructors
Problem: what if object contains a pointer?
#include
C++: Classes & Objects -2 42
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 43
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
pointer1’s name pointer pointer2’s name pointer Dynamically allocated memory John Smith
C++: Classes & Objects -2 44
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 45
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; }
46
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 47
Copy Constructors
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
parameter list in the
PersonInfo( const PersonInfo & obj)
48
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 11-49
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;} };
11-50
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+ operator=
is the overloaded
+
is the overloaded
=
operator and operator 11-51
Operator Overloading
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.
11-52
Operator Overloading
Prototype: void operator=(const SomeClass &rval) return type function name parameter for object on right side of operator Operator is called via object on left side C++: Classes & Objects -2 53
Operator Function Overloading
#include
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 54
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 55
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 jim Object contains: Jim Young, 27 The bob Object contains: Jim Young, 27 The clone Object contains: Bob Faraday, 32
C++: Classes & Objects -2 56
= 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 57
= 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 58
Overloading Operators as Instance Members
#ifndef _LENGTH_H #define _LENGTH_H #include
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
11-60
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
11-61
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 inches 2 feet 6 inches 9 3 feet (-6) Want operator functions to allow this type of non standard addition and subtraction C++: Classes & Objects -2 62
FeetInches.h
#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 63
}
FeetInches.cpp
// Implementation file for the FeetInches class #include
C++: Classes & Objects -2 64
FeetInchesMain.cpp
int feet, inches; FeetInches first, second, third; PROGRAM OUTPUT // Get a distance from the user.
cout << "Enter a distance in feet and inches: "; cin >> feet >> inches; 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.
// 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: "; cin >> feet >> 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; // Display the result.
cout << "first - second = "; cout << third.getFeet() << " feet, "; cout << third.getInches() << " inches.\n";
C++: Classes & Objects -2 65
Overloading >, < and == operators
Now I’d like to compare to
FeetInches
another or if the two are equal objects to determine if one is less than another, greater than 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 66
Overloading >, < and == operators
Include these statements in
FeetInches.h
bool operator > (const FeetInches &); bool operator < (const FeetInches &); bool operator == (const FeetInches &); // Overloaded > // Overloaded < // 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) { 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) { bool status; if (feet == right.feet && inches == right.inches) status = true; else status = false; return status; }
C++: Classes & Objects -2 67
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: "; cin >> feet >> 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 a distance in feet and inches: 6 10 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 68
Overloading Types of Operators
++ , --
operators overloaded differently for prefix vs. postfix notation Overloaded relational operators should return a
bool
value Overloaded stream operators
>>
,
<< istream
,
ostream ostream
objects as parameters must return objects and take
istream
,
See project Length1-Overloaded
11-69
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
[]
itself returns a reference to object, not an object 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 11-70
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 11-71
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 11-72
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 like: int d = distance; object, allows statements C++: Classes & Objects -2 73
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;)
11-74
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
11-75
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
11-76
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 11-77
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
11-78
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 11-79
Object Composition
class StudentInfo { private: string firstName, LastName; string address, city, state, zip; ...
}; class Student { private: StudentInfo personalData; ...
};
11-80
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);
11-81
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 { private: string name; Date dateOfBirth; public: Person(string name, string month, int day, int year): dateOfBirth(month, day, year) { this->name = name;} };
11-82
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 { private: string name; Date dateOfBirth; public: Person(string name, string month, int day, int year): name(name), dateOfBirth(month, day, year) { //body is empty due to initialization lists } };
11-83
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 11-84
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 11-85
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) { } 11-86
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 11-87
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 11-88
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 " <
11-89
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"; } };
11-90
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"<
11-91
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
11-92
11.10 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 11-93
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
11-94
Inheritance Syntax and Notation
// Existing class class Base { }; // Derived class { }; Inheritance Class Diagram class Derived : public Base Base Class Derived Class
11-95
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 a; void bf(); int c; void df();
11-96
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; public: void setMajor(Discipline d) { major = d; } Discipline getMajor() { return major; } void setAdvisor(Person *p) { advisor = p; } Person *getAdvisor() { return advisor; } };
11-97
Inheritance of Members
class Faculty:public Person { private: Discipline department; public: void setDepartment(Discipline d) { department = d; } Discipline getDepartment( ) { return department; } }; Project Inheritance
11-98
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 11-99
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 11-100
Base Class Access Specification Base class access specification:
determines how
private
,
protected
, and
public
members of base class can be accessed by derived classes 11-101
Base Class Access
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{ };
11-102
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 11-103
Member Access Specification
Specified using the keywords
private
,
protected
,
public class MyClass { private : int a; protected : int b; void fun(); public : void fun2(); };
11-104
Base Class Access Specification
class Child : public Parent }; { protected: int a; public: Child(); base access member access
11-105
Base Class Access Specifiers
1) 2) 3) 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.
11-106
11-107
Effect of Base Access
Base class members How base class members appear in derived class private: x protected: y public: z private base class x inaccessible private: y private: z private: x protected: y public: z protected base class x inaccessible protected: y protected: z private: x protected: y public: z public base class x inaccessible protected: y public: z
11-108
More Inheritance vs. Access
class Grade private members: char letter; float score; void calcGrade(); public members: void setScore(float); float getScore(); char getLetter();
class Test : public Grade
private members: int numQuestions; float pointsEach; int numMissed; public members: Test(int, int); When Test from Grade class inherits class using public class access, it looks like this: private members: int numQuestions: float pointsEach; int numMissed; public members: Test(int, int); void setScore(float); float getScore(); float getLetter(); Inheritance & Polymorphism 109
More Inheritance vs. Access
class Grade private members: char letter; float score; void calcGrade(); public members: void setScore(float); float getScore(); char getLetter();
class Test : protected Grade
private members: int numQuestions; float pointsEach; int numMissed; public members: Test(int, int); When Test from Grade class inherits class using protected class access, it looks like this: private members: int numQuestions: float pointsEach; int numMissed; public members: Test(int, int); protected members: void setScore(float); float getScore(); float getLetter(); Inheritance & Polymorphism 110
More Inheritance vs. Access
class Grade private members: char letter; float score; void calcGrade(); public members: void setScore(float); float getScore(); char getLetter();
class Test : private Grade
private members: int numQuestions; float pointsEach; int numMissed; public members: Test(int, int); When Test from Grade class inherits class using private class access, it looks like this: private members: int numQuestions: float pointsEach; int numMissed; void setScore(float); float getScore(); float getLetter(); public members: Test(int, int); Inheritance & Polymorphism 111
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 "<
11-112
• • • •
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() Within Base - x, y, and Derived: protected Derived – y, z, getX() Main – nothing Base • • Derived: private Base Derived – y, z, getX() Main – nothing z are always directly accessible 11-113
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 11-114
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
11-115
Order of Execution
// 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 11-116
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 11-117
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;} };
11-118
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);
inheritance2.h is the declaration in
Student::Student(string sname, Discipline d, Person *adv):Person(sname) {major=d; advisor = adv;}
in inheritance2.cpp is the definition
11-119
#include
11-120
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 11-121
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();
11-122
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 π*r 2 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 123
Getting in “Shape”
class Shape{ private: double area; public: void setArea(double a) {area = a;} double getArea() {return area;} }; class Circle: public Shape { private: double radius; public: void setRadius(double r){ radius = r; setArea(3.14*r*r); } double getRadius() {return radius;} };
Inheritance & Polymorphism 124
Getting in “Shape”
#include
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 125
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 126
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 127
Getting in “Shape”
#include
Area of the circle is 314 Area of the rectangle is 54
Inheritance & Polymorphism 128
Problem with Redefining
Consider this situation: Class BaseClass y() . x() defines functions x() calls y() . and Class DerivedClass BaseClass inherits from and redefines function y() .
An object D of class DerivedClass and function x() is called. is created When x() is called, which y() defined in BaseClass in DerivedClass ?
is used, the one or the the redefined one Inheritance & Polymorphism 129
Problem with Redefining
BaseClass void X(); void Y();
Object D invokes function X() in BaseClass .
DerivedClass void Y();
function X() invokes function Y() BaseClass , not function Y() in in DerivedClass , because function calls are bound at compile time. DerivedClass D; D.X(); This is static binding.
Inheritance & Polymorphism 130
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