Download presentation
Presentation is loading. Please wait.
1
Classes
2
Chapter Goals To understand the concept of encapsulation To master the separation of interface and implementation To be able to implement your own classes To understand how constructors and member functions act on objects To discover appropriate classes for solving programming problems To distribute a program over multiple source files
3
Object-Oriented Programming
Did you know that you already are an Object Oriented Programmer?
4
Object-Oriented Programming
Does string sound familiar?
5
Object-Oriented Programming
Does string sound familiar? How about cin and cout? (Yes, but...)
6
Object-Oriented Programming
An Object Oriented Programmer uses objects. (Wow, I didn’t realize…)
7
Object-Oriented Programming
But… a REAL Object Oriented Programmer designs and creates objects and then uses them. (Back to square 1 for me) (At least it’s not square 0 – that would be the very start.)
8
Object-Oriented Programming
Yes, you are mostly A Programmer Who Writes Functions To Solve Sub-problems And that is very good!
9
Object-Oriented Programming
As programs get larger, it becomes increasingly difficult to maintain a large collection of functions. It often becomes necessary to use the dreaded and deadly practice of USING GLOBAL VARAIBLES (Don’t do it!)
10
Object-Oriented Programming
Global variables are those defined outside of all functions – so all functions have access to them. But…
11
Object-Oriented Programming
When some part of the global data needs to be changed: to improve performance or to add new capabilities, a large number of functions may be affected – you will have to rewrite them – and hope everything still works!
12
Object-Oriented Programming
When some part of the global data needs to be changed: to improve performance or to add new capabilities, a large number of functions may be affected – you will have to rewrite them – and hope everything still works! Ouch!
13
No more global variables – Hurray!
Objects to the Rescue Computer scientists noticed that most often functions were working on related data so they invented: Objects where they keep the data and the functions that work with them together. No more global variables – Hurray!
14
Object Oriented Programming
Objects to the Rescue objects Object Oriented Programming (OOP)
15
The data stored in an object are called: data members
Objects to the Rescue Some new terminology. The data stored in an object are called: data members The functions that work on data members are: member functions No more variables and functions – separately.
16
Figure out which functions go with which data.
Objects to the Rescue Figure out which functions go with which data.
17
Create an object for each set of data.
Objects to the Rescue Create an object for each set of data.
18
Create another object for another set.
Objects to the Rescue Create another object for another set.
19
Objects to the Rescue And now, a third object.
20
Objects to the Rescue
21
Get rid of those global variables.
Objects to the Rescue Get rid of those global variables.
22
From now on, we’ll have only objects.
Objects to the Rescue From now on, we’ll have only objects.
23
Objects to the Rescue Ah.
24
Encapsulation The data members are encapsulated They are hidden from other parts of the program and accessible only through their own member functions.
25
Now when we want to change the way that an object is implemented,
Encapsulation Now when we want to change the way that an object is implemented, only a small number of functions need to be changed, and they are the ones in the object.
26
Because most real-world programs need
Encapsulation Because most real-world programs need to be updated often during their lifetime, this is an important advantage of object-oriented programming. Program evolution becomes much more manageable. (Ah …)
27
When you use string or stream objects,
Encapsulation When you use string or stream objects, you did not know their data members. Encapsulation means that they are hidden from you. (That’s good – you might have messed them up.)
28
Encapsulation and the Interface
But you were allowed to call member functions such as substr, and you could use operators such as [] or >> (which are actually functions). You were given an interface to the object.
29
Encapsulation and the Interface
All those member functions and operators are the interface to the object.
30
Encapsulation and the Interface
I wonder how the engine really works, and the speedometer, and the gas gauge, and that little thingy over there…
31
Encapsulation and the Interface
And I better stop thinking about all this or I won’t be able to drive!
32
Object-Oriented Programming
So you like my interface. Don’t get me started…
33
In C++, a programmer doesn’t implement a single object.
Classes In C++, a programmer doesn’t implement a single object. Instead, the programmer implements a class.
34
A class describes a set of objects with the same behavior.
Classes A class describes a set of objects with the same behavior. You would create the Car class to represent cars as objects.
35
Object-Oriented Programming
An object ?!
36
you must specify the behavior
Defining Classes To define a class, you must specify the behavior by providing implementations for the member functions, and by defining the data members for the objects …
37
Classes To define a class: Implement the member functions to specify the behavior. Define the data members to hold the object’s data.
38
We will design a cash register object.
Designing the Class We will design a cash register object.
39
Designing the Class By observing a real cashier working, we realize our cash register design needs member functions to do the following: • Clear the cash register to start a new sale. • Add the price of an item. • Get the total amount owed and the count of items purchased.
40
These activities will be our public interface.
Classes These activities will be our public interface. The public interface is specified by declarations in the class definition. The data members are defined there also.
41
To define a class you write:
Classes To define a class you write: class NameOfClass { private: // the data members public: // the public interface };
42
Classes Any part of the program should be able to call the member functions – so they are in the public section. Data members are defined in the private section of the class. Only member functions of the class can access them. They are hidden from the rest of the program. class NameOfClass { private: // the data members public: // the public interface };
43
Here is the C++ syntax for the CashRegister class definition:
Classes Here is the C++ syntax for the CashRegister class definition: class CashRegister { private: // data members will go here public: void clear(); void add_item(double price); double get_total() const; int get_count() const; };
44
Classes The public interface has the three activities that we decided this object should support. class CashRegister { private: // data members will go here public: void clear(); void add_item(double price); double get_total() const; int get_count() const; };
45
Notice that these are declarations. They will be defined later.
Classes Notice that these are declarations. They will be defined later. class CashRegister { private: // data members will go here public: void clear(); void add_item(double price); double get_total() const; int get_count() const; };
46
Methods There are two kinds of member functions: Mutators Accessors
47
A mutator is a function that modifies the data members of the object.
Mutators A mutator is a function that modifies the data members of the object.
48
Mutators CashRegister has two mutators: clear class CashRegister { public: void clear(); void add_item(double price); double get_total() const; int get_count() const; private: // data members will go here };
49
Mutators CashRegister has two mutators: clear and add_item. class CashRegister { public: void clear(); void add_item(double price); double get_total() const; int get_count() const; private: // data members will go here };
50
Mutators You call the member functions by first creating a variable of type CashRegister and then using the dot notation: Because these are mutators, the data stored in the class will be changed. CashRegister register1; ... register1.clear(); register1.add_item(1.95);
51
Mutators
52
An accessor is a function that queries a data member of the object.
Accessors An accessor is a function that queries a data member of the object. It returns the value of a data member to its caller.
53
CashRegister has two accessors: get_total
class CashRegister { public: void clear(); void add_item(double price); double get_total() const; int get_count() const; private: // data members will go here }; C++ for Everyone by Cay Horstmann Copyright © 2012 by John Wiley & Sons. All rights reserved
54
Accessors CashRegister has two accessors: get_total and get_count. class CashRegister { public: void clear(); void add_item(double price); double get_total() const; int get_count() const; private: // data members will go here };
55
Accessors Because accessors should never change the data in an object, you should make them const . class CashRegister { public: void clear(); void add_item(double price); double get_total() const; int get_count() const; private: // data members will go here }; not here
56
This statement will print the current total:
Accessors This statement will print the current total: cout << register1.get_total() << endl;
57
Mutators and Accessors: The Interface
The interface for our class:
58
Class Definition Syntax
59
Common Error: Can you find the error? class MysteryClass { private: ... public: } int main()
60
Common Error: Missing Semicolon
Don’t forget that semicolon! class MysteryClass { private: ... public: }; // Forgot semicolon int main() // Many compilers report // that error here in main! }
61
Let’s continue with the design of CashRegister.
Encapsulation Let’s continue with the design of CashRegister. Each CashRegister object must store the total price and item count of the sale that is currently rung up. We have to choose an appropriate data representation.
62
Encapsulation This is pretty easy:
63
Encapsulation item_count for the count class CashRegister { public: // interface private: int item_count; double total_price; };
64
Encapsulation total_price for the total class CashRegister { public: // interface private: int item_count; double total_price; };
65
Every CashRegister object has a separate copy of these data members.
Encapsulation Every CashRegister object has a separate copy of these data members. CashRegister register1; CashRegister register2;
66
Encapsulation
67
Because the data members are private, this won’t compile:
Encapsulation Because the data members are private, this won’t compile: int main() { ... cout << register1.item_count; // Error—use get_count() instead }
68
A good design principle: Never have any public data members.
Encapsulation A good design principle: Never have any public data members. Son, consider that an addition to the RULES! I know you can make data members public, but don’t. Just don’t do it!
69
Encapsulation and Methods as Guarantees
One benefit of the encapsulation mechanism is we can make guarantees.
70
Encapsulation and Methods as Guarantees
We can write the mutator for item_count so that item_count cannot be set to a negative value. If item_count were public, it could be directly set to a negative value by some misguided (or worse, devious) programmer.
71
Encapsulation and Methods as Guarantees
There is a second benefit of encapsulation that is particularly important in larger programs: Things Change.
72
Encapsulation and Methods as Guarantees
Well, that’s not really a benefit. Things change means: Implementation details often need to change over time …
73
Encapsulation and Methods as Guarantees
You want to be able to make your classes more efficient or more capable, without affecting the programmers that use your classes. The benefit of encapsulation is: As long as those programmers do not depend on the implementation details, you are free to change them at any time.
74
The Interface The interface should not change even if the details of how they are implemented change.
75
The Interface A driver switching to an electric car does not need to relearn how to drive.
76
Implementing the Member Functions
Now we have what the interface does, and what the data members are, so what is the next step? Implementing the member functions.
77
Implementing the Member Functions
The details of the add_item member function: void add_item(double price) { item_count++; total_price = total_price + price; }
78
Implementing the Member Functions
Unfortunately this is NOT the add_item member function. It is a separate function, just like you used to write. It has no connection with the CashRegister class void add_item(double price) { item_count++; total_price = total_price + price; }
79
Implementing the Member Functions
To specify that a function is a member function of your class you must write CashRegister:: in front of the member function’s name:
80
Implementing the Member Functions
To specify that a function is a member function of your class you must write CashRegister:: in front of the member function’s name: Not here void CashRegister::add_item(double price) { item_count++; total_price = total_price + price; }
81
Implementing the Member Functions
Use CashRegister:: only when defining the function – not in the class definition. class CashRegister { private: ... public: }; Not here Only here void CashRegister::add_item(double price) { item_count++; total_price = total_price + price; }
82
We are changing data members …
Implicit Parameters Wait a minute. We are changing data members … BUT THERE’S NO VARIABLE TO BE FOUND! Which variable is add_item working on?
83
Implicit Parameters Oh No! We’ve got two cash registers! CashRegister register2; CashRegister register1; Which cash register is add_item working on?
84
When a member function is called:
Implicit Parameters When a member function is called: The variable to the left of the dot operator is implicitly passed to the member function. In the example, register1 is the implicit parameter. CashRegister register1; ... register1.add_item(1.95);
85
The variable register1 is an implicit parameter.
Implicit Parameters The variable register1 is an implicit parameter. register1.add_item(1.95); void CashRegister::add_item(double price) { implicit parameter.item_count++; implicit parameter.total_price = implicit parameter.total_price + price; }
86
Implicit Parameters
87
Calling a Member Function from a Member Function
Let’s add a member function that adds multiple instances of the same item.
88
Calling a Member Function from a Member Function
Like when we are programming… and we get a dozen strong, black coffees to go. $5
89
Calling a Member Function from a Member Function
We have already written the add_item member function and the same good design principle of code reuse with functions is still fresh in our minds, so: void CashRegister::add_items(int qnt, double prc) { for (int i = 1; i <= qnt; i++) add_item(prc); }
90
Calling a Member Function from a Member Function
When one member function calls another member function on the same object, you do not use the dot notation. void CashRegister::add_items(int qnt, double prc) { for (int i = 1; i <= qnt; i++) add_item(prc); }
91
Calling a Member Function from a Member Function
So how does this work? Remember our friend: implicit parameter ! It’s as if it were written to the left of the dot (which also isn’t there) register1.add_items(6,0.95); void CashRegister::add_items(int qnt, double prc) { for (int i = 1; i <= qnt; i++) implicit parameter.add_item(prc); }
92
Calling a Member Function from a Member Function
93
The Cash Register Program
#include <iostream> #include <iomanip> using namespace std; /** A simulated cash register that tracks the item count and the total amount due. */
94
The Cash Register Program
class CashRegister { private: int item_count; double total_price; public: double get_total() const; total amount of the current sale*/ int get_count() const; item count of the current sale*/ void clear(); /* Zero out item count and total. */ void add_item(double price); /** Adds an item to this cash register.*/ };
95
The Cash Register Program
int CashRegister::get_count() const { return item_count; } double CashRegister::get_total() const { return total_price; void CashRegister::clear(){ item_count = 0; total_price = 0; void CashRegister::add_item(double price){ item_count++; total_price = total_price + price;
96
The Cash Register Program
/** Displays the item count and total price of a cash register. @param reg the cash register to display */ void display(CashRegister reg) { cout << reg.get_count() << " $" << fixed << setprecision(2) << reg.get_total() << endl; } This is not a member function !!!
97
The Cash Register Program
int main() { CashRegister register1; register1.clear(); register1.add_item(1.95); display(register1); register1.add_item(0.95); register1.add_item(2.50); display(register1); // non-member function return 0; }
98
const Correctness You should declare all accessor functions in C++ with the const reserved word.
99
But let’s say, just for the sake of checking things out
const Correctness But let’s say, just for the sake of checking things out – you would never do it yourself, of course – suppose you did not make display const: class CashRegister { void display() const; // Bad style—no const ... };
100
This will compile with no errors.
const Correctness This will compile with no errors.
101
But son, it’s not just about you.
const Correctness But son, it’s not just about you.
102
Very correctly she makes the array const.
const Correctness What happens when some other, well intentioned, good design-thinking programmer uses your class, an array of them actually, in a function. Very correctly she makes the array const. void display_all(const CashRegister[] registrs) { for (int i = 0; i < NREGISTERS; i++) registrs[i].display(); }
103
Son, look what you’ve done!
const Correctness Son, look what you’ve done!
104
void display_all(const CashRegister[] registrs) {
const Correctness The compiler (correctly) notices that registrs[i].display() is calling a NON-CONST display method on a CONST CashRegister object. void display_all(const CashRegister[] registrs) { for (int i = 0; i < NREGISTERS; i++) registrs[i].display(); } compiler error
105
const Correctness Son… Yes, it’s actually her fault for not reading your code closely enough but that is no excuse for your bad behavior.
106
Constructors House house1; House house2; House house3; ...
A friendly construction worker reading a class definition
107
(It doesn’t construct?)
Constructors A constructor is a member function that initializes the data members of an object. (It doesn’t construct?)
108
The constructor is automatically called whenever an object is created.
Constructors The constructor is automatically called whenever an object is created. CashRegister register1; (You don’t see it but it’s there.)
109
By supplying a constructor,
Constructors By supplying a constructor, you can ensure that all data members are properly set before any member functions act on an object. (Ah, consistency …)
110
By supplying a constructor,
Constructors By supplying a constructor, you can ensure that all data members are properly set before any member functions act on an object. What would be the value of a data member that was not (no way!) properly set? GARBAGE
111
“Garbage” is a technical computer science term.
Constructors “Garbage” is a technical computer science term. It means… …well… “garbage.”
112
CashRegister register1; register1.add_item(1.95);
Constructors To understand the importance of constructors, consider the following statements: CashRegister register1; register1.add_item(1.95); int count = get_count(); // May not be 1 Notice that the programmer forgot to call clear before adding items. (Recall that technical computer science term and what it means?)
113
CashRegister register1; register1.add_item(1.95);
Constructors To understand the importance of constructors, consider the following statements: CashRegister register1; register1.add_item(1.95); int count = get_count(); // May not be 1 Notice that the programmer forgot to call clear before adding items. (A “garbage” value is not to be trusted.)
114
Constructors Constructors are written to guarantee that an object is always fully and correctly initialized when it is defined.
115
You declare constructors in the class definition:
class CashRegister { public: CashRegister(); // A constructor ... };
116
The name of a constructor is identical to the name of its class:
Constructors The name of a constructor is identical to the name of its class: class CashRegister { public: CashRegister(); // A constructor ... };
117
There must be no return type, not even void.
Constructors There must be no return type, not even void. class CashRegister { public: CashRegister(); // A constructor ... };
118
And, of course, you must define the constructor.
Constructors And, of course, you must define the constructor. CashRegister::CashRegister() { item_count = 0; total_price = 0; }
119
Constructors To connect the definition with the class, you must use the same :: notation CashRegister::CashRegister() { item_count = 0; total_price = 0; }
120
You should choose initial values
Constructors You should choose initial values for the data members so the object is correct. CashRegister::CashRegister() { item_count = 0; total_price = 0; }
121
And still no return type.
Constructors And still no return type. CashRegister::CashRegister() { item_count = 0; total_price = 0; }
122
A constructor with no parameters is called a default constructor.
Constructors A constructor with no parameters is called a default constructor. CashRegister::CashRegister() { item_count = 0; total_price = 0; }
123
Default constructors are called when you define an object
and do not specify any parameters for the construction. Notice that you do NOT use an empty set of parentheses. CashRegister register1;
124
Constructors register1.item_count and register1.total_price are set to zero as they should be. CashRegister register1;
125
Constructors can have parameters, and constructors can be overloaded:
class BankAccount { public: // Sets balance to 0 BankAccount(); // Sets balance to initial_balance BankAccount(double initial_balance); // Member functions omitted private: double balance; };
126
Constructors When you construct an object, the compiler chooses the constructor that matches the parameters that you supply: BankAccount joes_account; // Uses default constructor BankAccount lisas_account(499.95); // Uses BankAccount(double) constructor
127
They will be garbage if you don’t set them in the constructor.
Constructors It is good design to think about what values you should put in numeric and pointer data members. They will be garbage if you don’t set them in the constructor. Is that OK?
128
Data members of classes that have constructors will not be garbage.
For example, the string class has a default constructor that sets string s to the empty string ("").
129
Constructors THINK: is the default string OK? ... private: string name; double hourlyRate; }; THINK, then set.
130
Common Error: Trying to Use the Constructor to Reset
You cannot use a constructor to “reset” a variable. It seems like a good idea but you can’t: CashRegister register1; ... register1.CashRegister(); // Error
131
Constructors – The System Default Constructor
If you write no constructors at all, the compiler automatically generates a system default constructor that initializes all data members of class type with their default constructors (which is just garbage for numeric and pointer data members).
132
Initialization Lists When you construct an object whose data members are themselves objects, those objects are constructed by their class’s default constructor. However, if a data member belongs to a class without a default constructor, you need to invoke the data member’s constructor explicitly.
133
Initialization Lists A class to represent an order might not have a default constructor: class Item: public: Item(string item_descript, double item_price); // No other constructors ... };
134
Initialization Lists A class to represent an order would most likely have an Item type data member: class Order { public: Order(string customer_name, string item_descript, double item_price); ... private: Item article; string customer; };
135
Initialization Lists The Order constructor must call the Item constructor. This is done in the initializer list. The initializer list goes before the opening brace of the constructor by putting the name of the data member followed by their construction arguments: Order::Order(string customer_name, string item_description, double item_price) : article(item_description, item_price) ...
136
Initialization Lists Any other data members can also be initialized in the initializer list by putting their initial values in parentheses after their name, just like the class type data members. These must be separated by commas: Order::Order(string customer_name, string item_description, double item_price) : article(item_description, item_price), customer(customer_name) { } Notice there’s nothing to do in the body of the constructor now.
137
Recall how you hand traced code to help you understand functions.
Tracing Objects Recall how you hand traced code to help you understand functions. Adapting tracing for objects will help you understand objects. Grab some index cards (blank ones).
138
You know that the public: section is for others.
Tracing Objects You know that the public: section is for others. That’s where you’ll write methods for their use. That will be the front of the card. class CashRegister { private: int item_count; double total_price; public: void clear(); void add_item(double price); double get_total() const; int get_count() const; }; ... CashRegister reg1;
139
That will be the back of the card.
Tracing Objects You know that the private: section is for your data – they are not allowed to mess with it except through the public methods you provide. That will be the back of the card. class CashRegister { public: void clear(); void add_item(double price); double get_total() const; int get_count() const; private: int item_count; double total_price; }; ... CashRegister reg1;
140
Tracing Objects CashRegister reg1; When an object is constructed, add the variable’s name to the front of a card and fill in the initial values.
141
Tracing Objects CashRegister reg1; CashRegister reg2; You would do this for every variable.
142
Tracing Objects CashRegister reg1; CashRegister reg2; reg1.addItem(19.95); When a method is invoked, grab the right card...
143
Tracing Objects CashRegister reg1; CashRegister reg2; reg1.addItem(19.95); …flip it over…
144
…cross out the old values...
Tracing Objects CashRegister reg1; CashRegister reg2; reg1.addItem(19.95); …cross out the old values...
145
Tracing Objects CashRegister reg1; CashRegister reg2; reg1.addItem(19.95); …then write the new values below.
146
Suppose you are asked to get the sales tax.
Tracing Objects These cards can help you in development when you need to add more functionality: Suppose you are asked to get the sales tax.
147
You would add that to the front of the cards.
Tracing Objects You would add that to the front of the cards. Grab any card – they will all have to be redone. Add the newly requested method. Then flip it over and start thinking. get_sales_tax
148
You would add that to the front of the cards.
Tracing Objects You would add that to the front of the cards. Grab any card – they will all have to be redone. Add the newly requested method. Then flip it over and start thinking.
149
I have to calculate the sales tax.
Tracing Objects I have to calculate the sales tax. Do I have enough information here on the back of this card? I can only use these and any values passed in through parameters and global variables. get_sales_tax
150
Need a new data member: taxable_total.
Tracing Objects Tax rate? Need a new data member tax_rate for this which would be set in the constructor to a global constant. Are all items taxable? Need to add another parameter for taxable-or-not to add_item which would appropriately update... …what??? Need a new data member: taxable_total.
151
Tracing Objects Add these things and do some tracing. CashRegister reg2(TAX_RATE); reg2.addItem(3.95, false); reg2.addItem(19.95, true);
152
Now you get to actually use English in Object Oriented Programming!
Discovering Classes Do you recall all those little mini-English lessons we’ve been throwing in? Now you get to actually use English in Object Oriented Programming! (Hi!) (That’s Japanese for “yes”.)
153
Discovering Classes Using nouns and verbs
154
Discovering Classes One simple approach for discovering classes and member functions is to look for the nouns and verbs in the problem description.
155
Discovering Classes Often times, nouns correspond to classes, and verbs correspond to member functions.
156
Discovering Classes Many classes are abstractions of real-life entities. BankAccount CashRegister
157
The name for such a class should be a noun that describes the concept.
Discovering Classes Generally, concepts from the problem domain, be it science, business, or a game, make good classes. The name for such a class should be a noun that describes the concept. Other frequently used classes represent system services such as files or menus.
158
Not Discovering Classes
What might not be a good class? If you can’t tell from the class name what an object of the class is supposed to do, then you are probably not on the right track.
159
Not Discovering Classes
For example, you might be asked to write a program that prints paychecks. You start by trying to design a class PaycheckProgram.
160
Not Discovering Classes
class PaycheckProgram ? What would an object of this class do?
161
Not Discovering Classes
class PaycheckProgram ? ? An object of this class would have to do everything!
162
Not Discovering Classes
class PaycheckProgram ? ? ? That doesn’t simplify anything. A better class would be:
163
Discovering Classes class Paycheck ! ! ! ! !
164
Not Discovering Classes
Another common mistake, made particularly by those who are used to writing programs that consist of functions, is to turn an action into a class.
165
Not Discovering Classes
For example, if you are to compute a paycheck, you might consider writing a class ComputePaycheck.
166
Not Discovering Classes
class ComputePaycheck But can you visualize a “ComputePaycheck” object? A thing that is a computePaycheck?
167
Not Discovering Classes
class ComputePaycheck The fact that “computepaycheck” is not a noun tips you off that you are on the wrong track. On the other hand, a “paycheck” class makes intuitive sense. (The word “paycheck” is a noun.)
168
You can visualize a paycheck object.
Discovering Classes You can visualize a paycheck object. You can then think about useful member functions of the Paycheck class, such as compute_taxes, that help you solve the problem.
169
It is then helpful to consider how these classes are related.
“Has-a” relationship When you analyze a problem description, you often find that you have multiple classes. It is then helpful to consider how these classes are related. One of the fundamental relationships between classes is the “aggregation” relationship (which is informally known as the “has-a” relationship).
170
“Has-a” relationship The aggregation relationship states that objects of one class contain objects of another class.
171
Consider a quiz that is made up of questions.
“Has-a” relationship Consider a quiz that is made up of questions. Since each quiz has one or more questions, we say that the class Quiz aggregates the class Question (not to be confused with “begs the question”).
172
UML (Unified Modeling Language)
There is a standard notation to describe class relationships: a UML class diagram (Unified Modeling Language)
173
UML (Unified Modeling Language)
In the UML notation, aggregation is denoted by a line with a diamond-shaped symbol
174
UML (Unified Modeling Language)
The problem states that the Quiz object manages lots of Question objects. The code follows directly, using a vector to mange the Questions: class Quiz { }; ... private: vector<Question> questions;
175
Discovering Classes In summary, when you analyze a problem description, you will want to carry out these tasks: • Find the concepts that you need to implement as classes. Often, these will be nouns in the problem description. • Find the responsibilities of the classes. Often, these will be verbs in the problem description. • Find relationships between the classes that you have discovered.
176
You will want to split your code into separate source files.
Separate Compilation When you write and compile small programs, you can place all your code into a single source file. When your programs get larger or you work in a team, that situation changes. You will want to split your code into separate source files.
177
There are two reasons why this split becomes necessary.
Separate Compilation There are two reasons why this split becomes necessary. First, it takes time to compile a file, and it seems silly to wait for the compiler to keep translating code that doesn’t change. If your code is distributed over several source files, then only those files that you changed need to be recompiled.
178
Separate Compilation The second reason becomes apparent when you work with other programmers in a team. It would be very difficult for multiple programmers to edit a single source file simultaneously. Therefore, the program code is broken up so that each programmer is solely responsible for a separate set of files.
179
There must be a path of communication between the files.
Separate Compilation If your program is composed of multiple files, some of these files will define data types or functions that are needed in other files. There must be a path of communication between the files. In C++, that communication happens through the inclusion of header files. Yes, #include.
180
The code will be in two kinds of files: header files
Separate Compilation The code will be in two kinds of files: header files (which will be #include-ed) source files (which should never be #include-ed)
181
Separate Compilation A header file contains the interface: Definitions of classes. Definitions of constants. Declarations of nonmember functions.
182
Separate Compilation A source file contains the implementation: Definitions of member functions. Definitions of non-member functions.
183
Separate Compilation There will also be either: a “tester” program (a.k.a. client/driver program) or the real problem solution This is where main goes.
184
cashregister.h cashregister.cpp
Separate Compilation For the CashRegister class, you create a pair of files: cashregister.h the interface – the class definition cashregister.cpp the implementation – all the member function definitions
185
Separate Compilation: The Cash Register Program
This is the header file, cashregister.h Notice the first two lines. There is an ending #endif at the end of the file. This makes sure the header is only included once. Always write these. Use the name of the as shown.
186
Separate Compilation: The Cash Register Program
#ifndef CASHREGISTER_H #define CASHREGISTER_H class CashRegister { private: int item_count; double total; public: CashRegister(); //Default ctor – zero item count and total. void clear(); // Clears the item count and the total. : }; #endif
187
Separate Compilation: The Cash Register Program
You include this header file whenever the definition of the CashRegister class is required. Since this file is not a standard header file, you must enclose its name in quotes, not <...>, when you include it, like this: #include "cashregister.h" And now the implementation (.cpp) file:
188
Separate Compilation: The Cash Register Program
Notice that the implementation file #includes its own header file. #include "cashregister.h" CashRegister::CashRegister(){ clear(); } void CashRegister::clear(){ item_count = 0; total_price = 0;
189
Separate Compilation: The Cash Register Program
void CashRegister::add_item(double price){ item_count++; total_price = total_price + price; } double CashRegister::get_total() const { return total_price; int CashRegister::get_count() const { return item_count;
190
They are part of the interface, not the implementation.
Separate Compilation Notice that the member function comments are in the header file, not the .cpp file. They are part of the interface, not the implementation.
191
Separate Compilation There’s no main! HELP! No, someone who wants to use your class will write their own main and #include your header. Like this:
192
Separate Compilation: The Cash Register Program
#include <iostream> #include <iomanip> #include "cashregister.cc" using namespace std; /** Displays item count and total price of a cash register. @param reg the cash register to display */ void display(CashRegister reg){ cout << reg.get_count() << " $“ << fixed << setprecision(2) << reg.get_total() << endl; }
193
Separate Compilation: The Cash Register Program
int main() { CashRegister register1; register1.clear(); register1.add_item(1.95); display(register1); register1.add_item(0.95); register1.add_item(2.50); return 0; }
194
Friend Functions - Friend functions are not member functions of any class. They can directly access any member of any class they are declared as friends. class Box { double width; public: double length; friend void printWidth( Box box ); friend Box operator+(const Box &b1, const Box &b2) void setWidth( double wid ); };
195
Friend Functions void Box::setWidth( double wid ) { width = wid; }
/* printWidth() is not a member function of any class. Because setWidth() is a friend of Box, it can directly access any member of this class */ void printWidth( Box box ) { cout << "Width of box : " << box.width <<endl;
196
Friend Functions int main() { Box box; box.setWidth(10.0);
// Use friend function to print the width. printWidth( box ); return 0; } Output: Width of box : 10
197
C++ for Everyone by Cay Horstmann
Copyright © 2012 by John Wiley & Sons. All rights reserved
198
Operator Overloading double operator+(const Box &b1, const Box &b2) {
double result = b1.width + b2.width; return result; } int main() { double res; Box b1, b2; b1.setWidth(10.0); b2.setWidth(20.0); res = b1 + b2; // lets you add objects!! cout << “Total width = “ << res << endl; return 0;
199
Operator Overloading int main() { Box b1, b2; b1.setWidth(10.0);
// Use friend function to print the width. cout << a << endl << b << endl; return 0; } Output: Box width: 10 Box width: 20
200
Overloading I/O with Objects
//output friend ostream& operator<<(ostream &out, Box &b) { out << “Box width:"<< b.width <<"\n"; return out; } //input friend istream& operator>>(istream &in, Box &b) { cout << “Enter width: \n"; in >> b.width; return in;
201
Overloading I/O with Objects
int main() { Box b1, b2; b1.setWidth(10.0); b2.setWidth(20.0); // Use friend function to print the width. cout << b1 << endl << b2 << endl; return 0; } Output: Box width: 10 Box width: 20
202
NAMESPACE POLUTION ERROR
FIX POLUTION OF NAMESPACE
203
Dynamically Allocating Objects How about dynamic objects? Fine:
Pointers to Objects Dynamically Allocating Objects How about dynamic objects? Fine:
204
Pointers to Objects CashRegister* register_pointer = new CashRegister;
BankAccount* account_pointer = new BankAccount(1000);
205
Accessing: The -> Operator
Because register_pointer is a pointer to a CashRegister object, the value *register_pointer denotes the CashRegister object itself. To invoke a member function on that object, you might call (*register_pointer).add_item(1.95);
206
Accessing: The -> Operator
The parentheses are necessary because in C++ the dot operator takes precedence over the * operator. The expression without the parentheses would be a syntax error: *register_pointer.add_item(1.95); // Error – you can’t apply . to a pointer
207
register_pointer->add_item(1.95);
Pointers to Objects Because calling a member function through a pointer is very common, the designers of C++ supply an operator to abbreviate the “follow pointer and access member” operation. That operator is written -> and usually pronounced as “arrow”. Here is how you use the “arrow” operator: register_pointer->add_item(1.95);
208
And now for another English sort of thing: The this pointer.
(Yes, it’s correct English) (if you are talking about C++.) Remember, way back there, when we said:
209
The variable register1 is the implicit parameter.
Implicit Parameters The variable register1 is the implicit parameter. this = register1 (assigned by the system) register1.add_item(1.95); void CashRegister::add_item(double price) { implicit parameter.item_count++; implicit parameter.total_price = implicit parameter.total_price + price; } this.
210
The this Pointer Each member function has a special parameter variable, called this, which is a pointer to the implicit parameter.
211
CashRegister::add_item
The this Pointer For example, consider the member function CashRegister::add_item
212
The this Pointer If you call ... register1.add_item(1.95) ... then the this pointer has type CashRegister* and points to the register1 object.
213
The this Pointer (I don’t see it.) No, but you can use it:
214
The this Pointer ... register1.add_item(1.95) ...
215
The this pointer is made to point to the implicit variable.
If you call ... register1.add_item(1.95) ... The this pointer is made to point to the implicit variable. (The system did that assignment behind your back.) (Thank you!) this
216
The this Pointer void CashRegister::add_item(double price) { this->item_count++; this->total_price = this->total_price + price; }
217
The this Pointer void CashRegister::add_item(double price) { this->item_count++; this->total_price = this->total_price + price; } this points at the that implicit parameter.
218
void CashRegister::add_item(double price) { this->item_count++;
The this Pointer void CashRegister::add_item(double price) { this->item_count++; this->total_price = this->total_price + price; } The this pointer is not necessary here, but some programmers like to use the this pointer to make it very, very clear that item_count is a data member and not a variable. The this pointer is not necessary here, but some programmers like to use the this pointer to make it very, very clear that item_count and total_price are data members—not (plain old) variables or parameters. C++ for Everyone by Cay Horstmann Copyright © 2012 by John Wiley & Sons. All rights reserved
219
Destructors and Resource Management
When a programmer uses new to obtain a dynamic array, she is requesting a system resource. And as all good recyclers know… …resources are limited and should be returned. peas recyple The this pointer is not necessary here, but some programmers like to use the this pointer to make it very, very clear that item_count is a data member and not a variable. C++ for Everyone by Cay Horstmann Copyright © 2012 by John Wiley & Sons. All rights reserved
220
Destructors and Resource Management
THE HEAP: No Entry Without Permission Of OS! Destructors and Resource Management class String { ... private: char* char_array; } String::String(const char initial_chars[]) char_array = new char[strlen(initial_chars) + 1]; strcpy(char_array, initial_chars); The characters of a String are stored on the heap, a system resource.
221
Destructors and Resource Management
Constructors don’t really construct (they initialize). There is another method that doesn’t really do what it’s name implies: the destructor. (Not in any way associated with professional wrestling.) The this pointer is not necessary here, but some programmers like to use the this pointer to make it very, very clear that item_count is a data member and not a variable.
222
Destructors and Resource Management
A destructor, like a constructor, is written without a return type and its name is the tilde character followed by the name of the class: ~ String (not to be confused with the dwiddle character) The this pointer is not necessary here, but some programmers like to use the this pointer to make it very, very clear that item_count is a data member and not a variable.
223
Destructors and Resource Management
A class can have only one destructor and it cannot have any parameters. String::~ String() { ... The this pointer is not necessary here, but some programmers like to use the this pointer to make it very, very clear that item_count is a data member and not a variable.
224
Destructors and Resource Management
Destructors don’t really destruct: String::~ String() { ... The this pointer is not necessary here, but some programmers like to use the this pointer to make it very, very clear that item_count is a data member and not a variable.
225
Destructors and Resource Management
Destructors don’t really destruct: they are used to recycle resources. String::~ String() { ... The this pointer is not necessary here, but some programmers like to use the this pointer to make it very, very clear that item_count is a data member and not a variable.
226
Destructors and Resource Management
Destructors don’t really destruct: they are used to recycle resources. String::~ String() { delete[] char_array; } The this pointer is not necessary here, but some programmers like to use the this pointer to make it very, very clear that item_count is a data member and not a variable.
227
Destructors and Resource Management
THE HEAP: No Entry Without Permission Of OS! Destructors and Resource Management The memory for the characters in a string are properly recycled.. void fun() { String name("Harry"); ... } Heap memory is allocated by the constructor Do you seen a method being invoked? Right there!
228
Destructors and Resource Management
THE HEAP: No Entry Without Permission Of OS! Destructors and Resource Management Destructors are automatically invoked when an object of that type is no longer needed. The memory for the characters in a string are properly recycled.. void fun() { String name("Harry"); ... } String::~String() is invoked right there.
229
Destructors and Resource Management
THE HEAP: No Entry Without Permission Of OS! Destructors and Resource Management Unfortunately, it’s a more complicated when assignment comes along: void no_fun() { String name1("Harry"); String name2("Sally"); name1 = name2; ... } Heap memory is allocated by both the constructors What happened to the memory for “Harry”? Now what?!
230
Destructors and Resource Management
This is not a topic covered in these slides. It involves: the destructor and another kind of constructor - the copy constructor and rewriting how the assignment operation works. These three topics together are called The Big Three. (Again, not in any way associated with professional wrestling.)
231
Object-Oriented Programming
Now I know you love me for the object I am!
232
Object-Oriented Programming
Hump h! Hrrrrr … Now I know you love me for the object I am!
233
Chapter Summary
234
Chapter Summary
235
Chapter Summary
236
Chapter Summary
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.