CSI 201 - Introduction to A class is a type definition that gives us - - PowerPoint PPT Presentation

csi 201 introduction to
SMART_READER_LITE
LIVE PREVIEW

CSI 201 - Introduction to A class is a type definition that gives us - - PowerPoint PPT Presentation

Review An object is a special variable that has data as well as member functions that act on that data. CSI 201 - Introduction to A class is a type definition that gives us a blueprint for creating objects of that type. Example classes


slide-1
SLIDE 1

CSI 201 - Introduction to Computer Science

Chapter 6 Defining classes Brian R. King Instructor

3/8/2006 CSI 201 -- Chapter 06 2

Review

  • An object is a special variable that has data as well as member functions

that act on that data.

  • A class is a type definition that gives us a blueprint for creating objects of

that type.

  • Example classes we've seen:
  • stream
  • fstream
  • istream
  • ifstream
  • An object is a variable whose type is a class.
  • We say an object is an instance of a class.
  • Example objects we've seen:
  • cin
  • cout
  • Goal of Chapter 6 - Learn how to define our own class
  • The complete class definition will define:
  • What kind of data the object can hold
  • What functions should exist to operate on that data.

3/8/2006 CSI 201 -- Chapter 06 3

Structures

A structure (or struct) is a simplified class, and

makes a good introduction to exploring classes.

Structs allow us to define new data types that are

am amalgam of other data types.

A good analogy of a struct is a record of a database.

A student record may include fields such as:

  • Name
  • Student ID
  • GPA
  • Status (1=freshman, … , 4 = senior, 5 graduate)

Structs are sometimes referred to as records in

some texts.

3/8/2006 CSI 201 -- Chapter 06 4

Struct definition syntax

struct Identifier

{ variable_declaration_1; variable_declaration_2; … variable_declaration_n; };

Identifier names the structure type. We call this the structure

tag.

It is an industry standard to have the first letter of a class or struct

name be a CAPITAL letter (This is not a C++ syntax requirement.)

Each one of the variable declarations between the braces are

referred to as the members of the struct, also called member names or member fields.

The structure definition ends with a semi-colon. The structure tag becomes a new data type for your program.

slide-2
SLIDE 2

3/8/2006 CSI 201 -- Chapter 06 5

The student record as a struct

struct Student { char name[30]; int id; double GPA; int status; };

Student is the structure tag above, and therefore

names a new type available in our program.

Student has 4 members. They are name, id, GPA

and status.

3/8/2006 CSI 201 -- Chapter 06 6

Declaring a struct variable

#include <iostream> using namespace std; struct Student { char name[30]; // Student name int id; // Student id double GPA; // Current GPA (0.0 - 4.0) int status; // Current status }; int main() { Student st; return 0; }

  • Our struct definition goes outside of any function, in the global declaration space. Why?
  • The struct definition defines a new type called Student.
  • The main program has a variable declaration of type Student called st.
  • The variable declaration for st allocates within it memory to store each of the members of

st.

3/8/2006 CSI 201 -- Chapter 06 7

Accessing members – the "dot" operator

  • The dot operator is used to access members of a struct variable.

cout << "Enter the student id: "; cin >> st.id; cout << "Enter the student's GPA: "; cin >> st.GPA; cout << "Enter current standing (1 = freshman ... 5 = graduate): "; cin >> st.status;

  • To the left of the dot operator is a struct variable.
  • To the right of the dot operator is a member name.
  • Struct members are treated just like any other variables, as long as

they are accessed through the dot operator.

  • Think about the type of the expressions in bold above. What type

are they?

  • Why wouldn't the following work? (Ask yourself, does an istream
  • bject know how to extract a variable of type Student?)
  • cin >> st;

3/8/2006 CSI 201 -- Chapter 06 8

Ex1.cpp

#include <iostream> #include <iomanip> #include <fstream> using namespace std; struct Student { int id; // Student id double GPA; // Current GPA (0.0 - 4.0) int status; // Current status (1 = freshman .. 4 = senior, 5 = graduate) }; int main() { Student st; cout << "Enter the student id: "; cin >> st.id; cout << "Enter the student's GPA: "; cin >> st.GPA; cout << "Enter their current standing (1 = freshman ... 4 = senior, 5 = graduate): "; cin >> st.status; cout.setf(ios::right); cout << setw(15) << "Student id: " << setw(10) << st.id << endl; cout << setw(15) << "GPA: " << setw(10) << st.GPA << endl; cout << setw(15) << "Status: " << setw(10) << st.status << endl; return 0; }

slide-3
SLIDE 3

3/8/2006 CSI 201 -- Chapter 06 9

More on structs…

  • Multiple struct definitions can have the same member names:

struct Employee { int id; int years; }; struct Student { int id; double GPA; int status; };

Both structs have members called id. This is legal because variable declarations inside of different

struct definitions are independent of each other.

  • They are tied to the struct in which they are defined.

3/8/2006 CSI 201 -- Chapter 06 10

Struct assignments

  • You can assign one struct variable to another struct variable, as long

as both variables are of the same type:

Student s1, s2; s1.id = 8675309; s1.GPA = 3.98; s2 = s1; // This is legal!

  • It's illegal to assign struct variables of different types:

Student st; Employee emp; st.id = 1234567; emp = st; // This is illegal!

3/8/2006 CSI 201 -- Chapter 06 11

Structures as function arguments

You can pass structures as parameters into

functions the same way you pass simple types as parameters.

Example:

bool isHonorStudent(Student& s);

It is not necessary for a struct parameter to be a

call-by-reference parameter. Do what makes sense for your program.

3/8/2006 CSI 201 -- Chapter 06 12

ex2.cpp – Structures within structures

struct Date { int month; int day; int year; }; struct Student { int id; // Student id Date bday; // Student birthday double GPA; // Current GPA (0.0 - 4.0) int status; // Current status };

You can also define a hierarchy of structures.

slide-4
SLIDE 4

3/8/2006 CSI 201 -- Chapter 06 13

ex2.cpp continued…

void print_student(Student &s, ostream &out); int main() { Student st; cout << "Enter the student id: "; cin >> st.id; cout << "Enter student's birthday as month day year: "; cin >> st.bday.month >> st.bday.day >> st.bday.year; cout << "Enter the student's GPA: "; cin >> st.GPA; cout << "Enter their current standing (1 = freshman ... 4 = senior, 5 = grad uate): "; cin >> st.status; print_student(st,cout); return 0; }

What type is st? What type is st.bday? What type is st.bday.month?

3/8/2006 CSI 201 -- Chapter 06 14

ex2.cpp continued…

void print_student(Student &s, ostream &out) {

  • ut.setf(ios::right);
  • ut << setw(15) << "Student id: " << setw(10) << s.id << endl;
  • ut << setw(15) << "Birthday: " << setw(2) << s.bday.month << "/"

<< setw(2) << s.bday.day << "/" << setw(4) << s.bday.year << endl;

  • ut << setw(15) << "GPA: " << setw(10) << s.GPA << endl;
  • ut << setw(15) << "Status: " << setw(10);

if (s.status == 1)

  • ut << "Freshman";

else if (s.status == 2)

  • ut << "Sophomore";

else if (s.status == 3)

  • ut << "Junior";

else if (s.status == 4)

  • ut << "Senior";

else if (s.status == 5)

  • ut << "Graduate";

else

  • ut << "UNKNOWN";
  • ut << endl;

}

3/8/2006 CSI 201 -- Chapter 06 15

Initializing structures

You can initialize structures at the time they are declared.

  • Simple structures:

struct Date { int month; int day; int year; }; Date d = { 12, 25, 2004 };

  • Hierarchical structures:

struct Student { char name[30];// Student name int id; // Student id Date bday; // Student birthday double GPA; // Current GPA (0.0 - 4.0) int status; // Current status }; Student s = { "Fred Jones", 123043243, { 12, 25, 2004 }, 3.23, 3 };

3/8/2006 CSI 201 -- Chapter 06 16

Questions…

  • SEE EX3.cpp
  • What happens if you don't have enough initializers for your struct

variable?

Student s = { "Fred Jones", 123043243, { 12, 25, 2004 }};

  • What happens if you have too many initializers for your structure

variable?

Student s = { "Fred Jones", 123043243, { 12, 25, 2004 }, 3.25, 3, 2};

  • What is the value of your structure variable if you don't initialize it?

Student s;

slide-5
SLIDE 5

3/8/2006 CSI 201 -- Chapter 06 17

Exercises

  • Consider the following:

struct ShoeType { char style; double price; };

  • Write a function called readShoe that initializes the members of a

ShoeType struct variable with values entered from the keyboard:

  • Write a function called discount that reduces the price of a

ShoeType struct variable by x percent:

3/8/2006 CSI 201 -- Chapter 06 18

Object Oriented Programming Defined

Some definitions from the web:

Object-oriented programming is a method of programming based

  • n a hierarchy of classes, and well-defined and cooperating
  • bjects. (java.sun.com)

Object-oriented programming (OOP) is a programming language

model organized around "objects" rather than "actions", and data rather than logic. (techtarget.com)

It's been said time and time again that OOP is "undoubtedly one

  • f the most complex programming techniques to explain."

(linuxgazette.com)

OOP is often called a "paradigm" rather than a style or type of

programming to emphasize the point that OOP can change the way software is developed, by changing the way programmers and software engineers think about software. (wikipedia.org)

OOP is a large field unto itself, and is WELL beyond the scope of

this class to teach you the paradigm. You will only be introduced in the most general sense to OOP, by showing you rudimentary skills required to define your own classes.

3/8/2006 CSI 201 -- Chapter 06 19

The essence of the OOP paradigm

  • The design methodology we've learned up to this

point is known as structural programming or procedural programming.

  • Object Oriented Programming offers a completely

different design methodology.

1.

Identify components in your program called OBJECTS, and determine how the objects interact with each other

2.

Specify the relevant data and possible operations to be performed on that data for each object.

3.

Combine the data and the operations on that data into a units called classes. Write your class definitions.

4.

The final program is a collection of interacting objects

  • OOP provides a model that is more in line with the

real world. Consider the next couple examples:

3/8/2006 CSI 201 -- Chapter 06 20

Salt and the OO Programmer

  • Suppose you are out to dinner with your friend. You want your friend

to pass the salt to you. You have two choices as to how ask your friend:

1.

"Pass the salt"

2.

"Please lower your fork to the table, drop the fork. Now, move your hand to the left, just a little more. There, now place your hand around the salt shaker, grasp it, lift it off the table. Good, now move the salt shaker in my

  • direction. Now, lower the salt shaker to the table, release your grip. Good,

now get your grubby hand away from me."

  • Which choice is the easier choice? (Obvious!)
  • You and your friend are objects. The salt is an object as well.
  • An OOP design is a collection of interacting objects. Interaction
  • ccurs by passing messages and invoking services.
  • In our above example, you send a message to your friend to "Pass the

salt." Your friend carry out the request any way he/she chooses.

  • The procedural way is for you to carry the burden of specifying every

step to your friend to get your task accomplished.

  • When objects respond to messages and services, the consumer
  • f the object's services is not concerned with how the request is
  • accomplished. Objects are responsible for their own actions.
slide-6
SLIDE 6

3/8/2006 CSI 201 -- Chapter 06 21

Okay… a relevant OOP example

Suppose you need to write system software for a bank, and you

are designing the part that handles reporting the balance of an account.

The structural / procedural way would require the programmer to

consider the original balance of the account, read and add all deposits into the account, subtract all checks and ATM transactions, consider any bank fees, then report the balance.

The OOP way would have an object of type Account that

represents the customer's account. Just ask the object to return the current balance!

The object is responsible for its own actions.

In this example, the Account object is responsible for keeping its

current balance updated at all time. Programmers using the

  • bject need not be concerned with how this is done.

Clearly, someone needs to design the Account class for this to

work, but this has most likely been done already.

  • This illustrates reusability – yet another big benefit of OOP and an

important software engineering concept.

3/8/2006 CSI 201 -- Chapter 06 22

Classes define Abstract Data Types

A well designed class keeps the details of how the

  • bject works away from the programmer using the
  • bject.

Illustrates the concept of the abstract data type – hide

unnecessary details of how the object accomplishes its task from the programmer.

This is an extension of the black-box concept already

introduced with functions.

Example:

int x = 10;

cout << x;

The object cout is handing a request to place the value of

integer x into its output stream.

I don't care how it's done. I know that cout will accomplish

my request.

3/8/2006 CSI 201 -- Chapter 06 23

Objects perform services

  • Objects perform services for those using the object. How?
  • 1. Through calling member functions on the object. For example:
  • ifstream fin;

fin.open("input.txt");

  • fin is an object of type ifstream.
  • pen is a member function.
  • Calling a member function on an object is a way of sending a message to

the object to perform a service.

  • Hey fin! Open the file "input.txt" and attach it to your input stream.
  • 2. Through using operators in conjunction with an object. Example:
  • int x;

cin >> x;

  • cin is an object of type istream.
  • >> is the extraction operator (a binary operator).
  • Using an operator on an object is another way of sending a request to an
  • bject to perform a service (to be covered in Chapter 8.)
  • "Hey cin! Place the value of integer x in your output stream."
  • Again, we don't care how the object handles our request. The object is

responsible for how the requests are handled.

3/8/2006 CSI 201 -- Chapter 06 24

Classes

A class is a structure that defines the data and the

member functions (or methods) to work on that data.

If a class is a data type whose variables are objects, then an

  • bject is a variable whose type is a class.

We've seen that a struct is a type that groups multiple

data into one type.

Structs have taken us halfway to defining classes. Structs are really a form of a class type. To obtain a class from a struct, you only need to add member

functions.

OOP uses the term encapsulation to refer to the

process of combining variables and functions into a single unit called a class.

slide-7
SLIDE 7

3/8/2006 CSI 201 -- Chapter 06 25

Defining a class…

First, determine what values should be used to

represent your class.

Then, determine what member functions should act on

that data.

Let's build our own definition of a Date class. What data do we need in order to properly represent a

Date? (Recall the struct definition of Date earlier…)

What types should be used to represent that data?

3/8/2006 CSI 201 -- Chapter 06 26

Class definition…

  • Remember our struct definition of Date:

struct Date { int month; int day; int year; };

  • Our class definition uses the keywords class and public…

class Date { public: int month; int day; int year; };

  • Accept "public:" for now… it'll be explained shortly.

3/8/2006 CSI 201 -- Chapter 06 27

Member function declarations

  • Recall that there are two parts to writing your own function: the

function declaration and the function definition. This is no different with member functions.

  • Member function declarations become part of the class definition.
  • Suppose we want to add a member function to output the date to

cout:

class Date { public: int month; int day; int year; void output(); };

  • Notice how the function declaration appears inside of the class
  • definition. This determines whether the function declaration is a

member function declaration or not.

3/8/2006 CSI 201 -- Chapter 06 28

Member function definitions

  • The syntax of a member function definition is:

Return_type Class_Name::Function_Name(Parameters) { Function Body Statements }

  • A member function definition uses the scope resolution operator ::
  • Whenever you see the :: operator in your program, the name of a class

is to the left of it. (How does this differ from the dot operator?)

  • The definition of our output member function is:

void Date::output() { cout << month << "/" << day << "/" << year; }

  • Notice that member functions have access to all the variables defined in

the class definition without using the dot operator.

  • Why? We have a new type of scope – class scope.
  • month, day and year have class scope with respect to class Date.
  • They are visible within all member function definitions of the class Date.
slide-8
SLIDE 8

3/8/2006 CSI 201 -- Chapter 06 29

Invoking a member function… ex4.cpp

To invoke a member function, you first need to declare

an object of that class.

Date d;

Once you have your object declared, to invoke a

member function, you use the dot operator.

d.month = 10; d.day = 31; d.year = 2004; d.output(); //Outputs date d to cout

Therefore, you use the dot operator to access the data

members and the member functions of the class.

The above is effectively sending a request to object d to

  • utput its date to the screen.

See ex4.cpp.

3/8/2006 CSI 201 -- Chapter 06 30

Information hiding

Good OOP demands that class definitions HIDE

implementation details.

This is a necessary part of object-oriented design. A

programmer does not want to be concerned with how an

  • bject carries out its services that he/she requests.

A class definition defines a new data type. But, a

class definition that adheres to hiding all implementation details is known as an Abstract Data Type (or ADT).

C++ introduces the keyword private for the

purpose of creating ADTs.

private will be used to set up a section of member

data and member functions that will be hidden from any function outside of our class.

3/8/2006 CSI 201 -- Chapter 06 31

Using private in the Date definition

class Date { private: int month; int day; int year; public: void output(ostream&); };

  • Good beginner OOP practice is to simply make your member variables private,

and your member functions public.

  • A member function of the class being defined has permission to access the

private members of its own class.

  • Thus, our definition of output does not need to change.
  • But, the program won't compile anymore if we try to access the member data
  • utside of the class!
  • Let's modify ex4.cpp to move the data members into their own "private" section,

and try to compile to prove this…

  • We still need more changes – functions that allow access to the private data.

3/8/2006 CSI 201 -- Chapter 06 32

Accessor and mutator member functions

  • "Access" or "accessor" member functions return current values of data

members to the caller.

  • These function names normally start with the word get.
  • "Mutator" functions alter or change the current values of data members.
  • These function names normally start with the word set.
  • Why do we need this?
  • The state of an object is determined by the current value of all its data

members.

  • You often need a way to check the state of the object. (For example,

fin.eof() returns the state of the end-of-file flag.

  • Accessor and mutator functions are an important part of the ADT
  • definition. Without them, you would have no way of accessing or

changing the data members of your object.

  • Furthermore, most operators don't work with objects. (eg.. +, -, <, >,

etc…) These operators only work with simple types by default.

  • Date d;

cin >> d; // This does not compile!

  • More importantly, WHY WOULD WE WANT THIS? (We'll see shortly)
slide-9
SLIDE 9

3/8/2006 CSI 201 -- Chapter 06 33

Why design an ADT?

A well-designed ADT defines an interface which

programmers must adhere to in order to use the class.

The public section of a class definition generally defines the

interface through which programmers can interact with objects of the ADT.

Furthermore, it shields the programmer from needing to know

any implementation details of your class.

The private section of a class definition, along with member

function definitions, define the implementation details.

By forcing programmers to adhere to the interface of your

ADT, it allows the underlying implementation details of your class to change at a later date, without ever affecting functions using the class.

3/8/2006 CSI 201 -- Chapter 06 34

Example

  • Consider the following example
  • Design an class to represent a point in the X-Y coordinate plane.
  • Suppose version 1.0 of your class used integers for the underlying data used to

represent a point.

  • Some new users want fractional points. So, you need to release 2.0 to use

floating point numbers instead of integers for the data members.

  • If you defined an ADT, then users must adhere to the interface of your ADT

and EVERYBODY can upgrade to 2.0 without any existing code needing to be changed unless they want to use the new features.

  • BUT – Without this type of design, consider the problems with this code:
  • Point p1, p2;

p1.x = 3; p1.y = 4; p2.x = -1; p2.y = 2; int xDiff = abs(p1.x – p2.x); int yDiff = abs(p1.y – p2.y);

  • What problems could occur upon upgrading to 2.0 of the Point class?

3/8/2006 CSI 201 -- Chapter 06 35

ex5.cpp

  • class Date

{ private: int month; int day; int year; public: int getMonth(); int getDay(); int getYear(); void setDate(int m, int d, int y); void input(); void output(); };

See ex5.cpp

3/8/2006 CSI 201 -- Chapter 06 36

Private member functions

Member functions don't have to all be public. You

could implement member functions only accessible by the class.

These are typically what we call "helper" functions.

They implement some repeated task that multiple member functions can make use of, but the programmer using your abstract data type has no need for.

For example, both input() and setDate()

member functions should be checking valid date entries, so let's add a helper function called "checkDate" to do this.

slide-10
SLIDE 10

3/8/2006 CSI 201 -- Chapter 06 37

checkDate member function

bool Date::checkDate() { if (month > 12 || month < 1) return false; if (day > 31 || day < 1) return false; if (year > 9999 || year < 1900) return false; return true; }

  • Remember, checkDate has class scope with respect to class Date. So, we

don't have to use the dot operator when accessing any of Date's members.

  • Other member functions using checkDate don't need to call checkDate using

the dot operator either. (Same reason as above – checkDate is a member of Date.)

  • We could have used the accessor functions instead of hard coding the variables

as well.

  • It's typically better OOP practice to always use the accessor functions.

3/8/2006 CSI 201 -- Chapter 06 38

ex6.cpp

We'll also add a second object of type Date

to illustrate that two objects of one class type both contain their own copies of data.

Execute ex6.cpp

Note how checkDate is declared in the private

section, and note the checkDate function calls.

3/8/2006 CSI 201 -- Chapter 06 39

Assignment operator

The assignment operator can be used with

classes in the same manner that it can be used with variables:

Date d1, d2; d1.setDate(3,10,2004); d2 = d1;

The default behavior of the assignment

  • perator with objects is to copy all member

data in the object on the right hand side of the assignment operator to the object on the left.

3/8/2006 CSI 201 -- Chapter 06 40

Return an object from a function

Functions can return objects just like functions can return

variables of any other type:

We can write a standard (non-member) function that adds a

number of years to an existing Date object and returns a new Date object.

Date add_years(Date old, int numYears) { Date n; n.setDate(old.getMonth(),

  • ld.getDay(),
  • ld.getYears() + numYears);

return n; }

See ex7.cpp.

slide-11
SLIDE 11

3/8/2006 CSI 201 -- Chapter 06 41

Modify ex7.cpp

We could have add_years be a member

function of the object instead of a regular

  • function. How would we make this

modification?

We'll make the modification in class:

3/8/2006 CSI 201 -- Chapter 06 42

Constructors

A constructor is a special member function

that "constructs" the object.

It is designed to perform initialization of

member variables (but can do other things as well.)

It has the following restrictions:

It must have the same name as the class of which

it is a member.

It has NO return type.

3/8/2006 CSI 201 -- Chapter 06 43

Date constructor

  • A constructor for the Date class would look as follows:

Date::Date(int m, int d, int y) { month = m; day = d; year = y; }

  • Providing a constructor allows you to initialize an object at the time you declare
  • it. For example:

Date myDate(3,10,2004);

  • This sets up a Date object called myDate with the value of 3/10/2004.
  • However, once you define at least one constructor, you must declare every
  • bject with one of your defined constructors.

Date myDate(3,10,2004), myOtherDate; // illegal!

  • This won't compile because myOtherDate is not being declared with a constructor

3/8/2006 CSI 201 -- Chapter 06 44

Default constructor

  • If you don't define any constructor, the compiler provides a default constructor

for you that allocates memory for all data members, but leaves the values of each member uninitialized. (In other words, all values will have garbage!)

  • It is good practice to define your own default constructor so you know what

values your objects have at all times.

  • You can define your own default constructor that is a constructor with no formal
  • parameters. For example:
  • Date::Date()

{ month = 1; day = 1; year = 1980; }

  • Then, this combined with the other constructor would allow for the following:

Date myDate(3,10,2004), myOtherDate;

  • myDate contains the date 3/10/2004 and myOtherDate contains the date 1/1/1980.
  • Do NOT use a set of empty parenthesis to call the default construct in an object

declaration:

  • Date myDate(3,10,2004), myOtherDate(); // WRONG!!!
  • See ex9.cpp. Let's modify it to remove the constructors, and see what the output
  • f the dates are to prove if there's garbage in the values without a constructor

defined

slide-12
SLIDE 12

3/8/2006 CSI 201 -- Chapter 06 45

Constructor initialization section

You will also see an alternate way of initializing data members of

your class in a constructor:

Date::Date(int m, int d, int y) : month(m), day(d), year(y) { }

Some or all of the member variables in a class can (optionally)

be initialized in the area called the constructor initialization section of a constructor definition.

This section goes after the parenthesis that ends the parameter

list and before the opening brace of the function body.

It consists of a colon, then a list of member variables, separated

by commas, with each variable's initial value in parenthesis.

Both methods presented for initializing data members in a

constructor are completely valid and equivalent.

3/8/2006 CSI 201 -- Chapter 06 46

Explicitly calling a constructor

  • If you wanted to assign a new value to a Date object later on after it's

been initialized, you can explicitly call a constructor to do so:

int main() { Date date1, date2(3,10,2004); cout << "Object date1 is: "; date1.output(); cout << "Object date2 is: "; date2.output(); // Explicitly call a constructor to set date1 to a new date date1 = Date(12,25,2004); cout << "Object date1 is now: "; date1.output(); return 0; }

  • A constructor used this way has an implicit return type of the class for

which it's defined. It returns a newly constructed object of the class.

3/8/2006 CSI 201 -- Chapter 06 47

The End