Chapter 11

advertisement
Class
Student Record
 Student ID
 First name
 Last name
 Gender
 major
 GPA
 How do we store the data?
Store Student Records in Variables
// For one student at a time
float GPA;
string firstName, lastName;
string major;
long id;
char gender;
…
3
Store Student Records in Parallel Arrays
const int MAX_STUDENTS = 100;
long
string
string
char
string
float
id
[MAX_STUDENTS];
firstName[MAX_STUDENTS];
lastName [MAX_STUDENTS];
gender
[MAX_STUDENTS];
major
[MAX_STUDENTS];
gpa
[MAX_STUDENTS];
C++ Data Types
simple
integral
enum
structured
floating
array struct union class
char short int long bool
float double long double
address
pointer reference
Store Student Records in Class
class Student
// “Student” is the identifier of this class
{
private: // indicates following variables are only accessible within class Student
long
id;
// data fields (something new in class)
string firstName;
string lastName;
char
gender;
string major;
float gpa;
public:
// indicates following methods can be used outside class Student
long
GetID ( )
// methods (something new in class)
{
...
}
void
SetID ( long id )
{
...
}
...
// semicolon after }
};
C++ Class
 Syntax:
class ClassName
{
private:
DataMemberList;
MethodMemberList1;
public:
MethodMemberList2;
};
 class, private, and public are key words.
 A class usually has two types of members: data fields and methods.
• Data fields should always be private!
• Method can be private or public. (We will explain this later.)
Class Object
class Student
{
private:
long
id;
string firstName;
...
};
// Student is a new data type!
Student stu1;
// stu1 is an object of Student.
// A class object is a variable of the class!
// A Student object is a variable of Student data type!
Class Methods
class Student
{
private:
long
id;
...
public:
...
void PrintStudentRecord ()
{
cout << setprecision(2) << fixed << endl;
cout << setw(8) << id << setw(15) << firstName
<< setw(15) << lastName << setw(8) << gender
<< setw(20) << major << setw(8) << gpa;
}
...
};
How to call this function?
You can only call this function if it is public!
Declare a class object and then Use the dot notation!
Call a Class Method
int main()
{
Student stu;
// Declare a Student object first.
...
// assume all data fields in stu are filled with values
stu.PrintStudentRecord(); // Use DOT notation.
...
return 0;
}
Didn’t we already know classes?!
cin >> base;
while ( !cin.eof() && (base < 2 || base > 9) )
{
// display message
cin.ignore(MAX_LINE_SIZE, ‘\n’);
cin >> base:
}
string str1, str2;
str1 = “”;
while(str1.length() < MAX_LENGTH)
{
cin >> str2;
str1 += str2;
}
Class Scope
 The identifier of a class member has class scope and
can only be used in the following cases:
 In a member function of that class
 After the . (dot) operator applied to an object of that
class (if it is declared as public)
 Other situations (not covered in this class)
 An identifier declared within a member function hides
a declaration of the same identifier whose scope
extends to or past the end of the member function's
class.
Use a data field in a member function
class Student
{
private:
long
id;
string firstName;
string lastName;
char
gender;
string major;
float gpa;
firstName, etc are data fields of Class Student:
they can be used directly in
member functions of Class Student!
public:
void PrintStudentRecord ()
{
cout << "Name : " << firstName
<< "Gender: " << gender
<< "Major : " << major
<< "GPA
: " << gpa
}
...
};
<<
<<
<<
<<
" " << lastName
endl
endl
endl;
<< endl
Call a member function after DOT
void main()
{
Student stu1;
...
stu1.PrintStudentRecord();
...
return 0;
} PrintStudentRecord is a public method of Class Student:
it can be used anywhere outside Class Student by DOT notation.
Access private data in a class
class Student
{
private:
long
id;
string firstName;
string lastName;
char
gender;
string major;
float gpa;
...
}
int main()
{
Student stu1;
...
cout << stu1.id;
...
}
No! DOT notation cannot be used
to access private data or methods!
// The data fields are private to a Student object. What
if we want to use their values in the main function?
Access private data in a class
class Student
{
private:
long
id;
string firstName;
string lastName;
char
gender;
string major;
float gpa;
public:
long GetID()
{
return id;
}
int main()
{
Student stu1;
...
cout << stu1.GetID();
...
}
Declare a public method to access
private data!
}
// The data fields are private to a Student object. What if we
want to use their values in the main function?
Input values to data fields
Student stu1;
...
stu1.firstName = “Alex”;
// NO! firstName is private!
stu1.SetFirstName(“Alex”);
// Yes! Declare a Set method
to input values to private
data fields!
class Student
{
private:
string firstName;
...
public:
void SetFirstName(string fname)
{
firstName = fname;
}
...
}
Initialize a class object
// Declare variable with initial value
int numStudents = 0;
// Can we declare a class variable with
initial value?
Student s1;
Use Class Constructors!
Class Constructor
class Student
{
private:
long
id;
char
gender;
string firstName, lastName, major;
float gpa;
public:
Student()
// Default
{
id = 1001;
firstName = “Alice”;
lastName = “Wonderland”;
gender = ‘F’;
major = “ComputerScience”;
gpa = 3.2;
}
};
// Syntax for constructor
// No returned data type!
constructor: no parameters!
Class Constructor With Parameters
class Student
{
private:
long
id;
char
gender;
string firstName, lastName, major;
float gpa;
public:
Student( long stuId, string fName, string lName,
char stuGender, string stuMajor, float stuGpa )
{
id = stuId;
firstName = fName;
The parameter names cannot
lastName = lName;
be the same as data fields!
gender = stuGender;
why?
major = stuMajor;
gpa = stuGpa;
}
};
Multiple Class Constructors
class Student
{
...
public:
Student( )
{
id = 1001;
firstName = "Alice";
lastName = "Wonderland";
gender = 'F';
major = "ComputerScience";
gpa = 3.2;
}
 You can define multiple
constructors for the same class.
 Different Constructors Must
Have Different Parameters.
 Which one to use depends on the
parameters during the object
declaration.
Student( long id, string fName, string lName,
char stuGender, string stuMajor, float stuGpa )
{
id = id;
firstName = fName;
lastName = lName;
gender = stuGender;
major = stuMajor;
gpa = stuGpa;
}
...
};
Invoke Class Constructor
 Constructor is called implicitly when class objects are declared.
// Default constructor is called
Student stu1;
// Parameterized constructor is called
Student stu2( 1002, "Johnny", "Depp", 'M',
"SoftwareEngineering", 2.8 );
//OR
//Student stu2;
//stu2 = ( 1002, "Johnny", "Depp", 'M', "SoftwareEngineering", 2.8 );
// The default constructor has set the
//
values for data members
stu1.PrintStudentRecord();
// The parameterized constructor has set the
//
values for data members
stu2.PrintStudentRecord();
// This will change the data fields
stu1.SetID();
Different parameters for different constructors
// will this work?
NO!
// will this work?
YES!
class Student
class Student
{
{
private:
private:
long
id;
long
id;
...
...
public:
public:
Student( long stuID )
Student( long stuID )
{
{
id = stuID;
id = stuID;
}
}
Student( long sID)
Student( int stuID )
{
{
id = sID;
id = stuID;
gender = ‘F’;
}
}
...
...
};
}; DIFFERENT refers to different data types and number of parameters, not names!
Default Constructor
// Default constructor is called
Student stu1;
 If you don’t define any constructor:
 There is a default constructor doing nothing generated
by the compiler
 If you define a constructor without any parameter:
 This is your new default constructor
 If you define a constructor with parameters:
 There is NO default constructor generated by the
compiler anymore!
Copy Constructor
 Declare an object which is exactly the same as another
object:
class Student
{
...
public:
Student( Student stu ) // Copy constructor:
{
// gets initial values from object stu
id = stu.id;
firstName = stu.firstName; // Use the DOT notation to access
lastName = stu.lastName; // the data field of stu!
gender = stu.gender;
major = stu.major;
gpa = stu.gpa;
}
...
};
Constructor Summary
 Define a constructor:
 NO returned-data type!
 Constructors have the SAME name as the class!
 Purpose: initialize a class object
 Default constructor:
 NO parameters.
 If no constructor is defined, a default constructor doing NOTHING will be automatically
generated.
 If there is any parameterized constructor defined, no automatic generated default
constructor anymore.
 Copy constructor:
 Initialize one object by copying data fields of another object.
 Use the DOT notation directly to access data fields of another object.
 Multiple constructors:
 Different constructors have DIFFERENT parameters!
 Different constructors are called based on the parameters during object declaration.
 Invoke constructor:
Student stu1; // call the default constructor
Student stu2( 1002, "Johnny", "Depp", 'M',
"SoftwareEngineering", 2.8 );
 Student stu4;
stu4 = Student( 1004, “Brad”, “Pitt”, ‘M’, “CS”, 3.6 );


Array of Class Objects
Student stuList[MAX_STUDENTS];
// An array of Student objects
 Each element is treated the same way as a Student
object!
 Everything applied to an integer array applied to an
object array!
Operations on an object array element
Student stuList[MAX_STUDENTS];
 Initialization:
stuList[i] = Student(stuList[i-1]);
 Assignment:
stuList[i].SetID(1001);
 Computation:
totalGPA += stuList[i].GetGPA();
Pass an object array as a parameter
Student stuList[MAX_STUDENTS];
// Given a student id, find the index of the student
// in the Student array. Return -1 if not found.
// Parameters: in, in, in
int FindIndex ( const Student sList[], int size, long id )
{
for ( int i = 0; i < size; i ++ )
if ( sList[i].GetID() == id )
return i;
return -1;
}
StudentList Class
class StudentList
{
private:
Student stuList[MAX_STUDENTS]; // An array of Students
int
numStudents;
public:
StudentList()
{
numStudents = 0;
}
...
};
// Treat an element of stuList the same way as a Student object!
//
//
Initialize a stuList element using constructor.
Print a stuList element by its PrintRecord() method.
StudentList Class
class StudentList
{
private:
Student stuList[MAX_STUDENTS];
int
numStudents;
public:
StudentList()
{
numStudents = 0;
}
void Read( int size )
{
long
id;
string firstName, lastName, major;
char
gender;
float gpa;
if ( size <= MAX_STUDENTS )
while ( numStudents < size )
{
cin >> id >> firstName >> lastName
>> gender >> major >> gpa;
stuList[numStudents] =
Student(id, firstName, lastName,
gender, major, gpa);
numStudents ++;
}
StudentList( int size )
{
numStudents = 0;
Read(size);
}
void Print()
{
for( int i = 0;
i < numStudents; i++ )
stuList[i].PrintRecord();
}
}
};
Read() is used in the constructor
before its definition!
StudentList Class
class StudentList
{
private:
Student stuList[MAX_STUDENTS];
int
numStudents;
public:
void Read( int size )
{
long
id;
string firstName, lastName, major;
char
gender;
float gpa;
if ( size <= MAX_STUDENTS )
while ( numStudents < size )
{
cin >> id >> firstName >> lastName
>> gender >> major >> gpa;
stuList[numStudents] =
Student(id, firstName, lastName,
gender, major, gpa);
numStudents ++;
}
}
void Print()
{
for( int i = 0;
i < numStudents; i++ )
stuList[i].PrintRecord();
}
StudentList()
{
numStudents = 0;
}
StudentList( int size )
{
numStudents = 0;
if ( size <= MAX_STUDENTS )
Read(size);
}
};
Another way to read into a Student List
// Suppose Student has a ReadRecord method
void Read( int size )
{
if ( size <= MAX_STUDENTS )
while ( numStudents < size )
{
stuList[numStudents].ReadRecord();
numStudents ++;
} // This is a better approach because
}
// operations related to one object
// should be done by that object!
// DECOMPOSITION!!
Information Hiding
 Hide data fields and supportive methods under private.
 Only methods that will be used by other classes or stand
alone functions are public.
 Treat your class object as a BLACK BOX:
data fields
Class Object
supportive methods
public methods
Helper methods are those
only used by member methods
in the same class.
Employee Class
class Employee
{
private:
string employeeID;
string firstName;
string lastName;
float payRate;
float weeklyHours;
float weeklySalary;
void
CalcSalary()
{
if ( weeklyHours <= OVERTIME )
weeklySalary = payRate * weeklyHours;
else
weeklySalary = OVERTIME_RATE * payRate * (weeklyHours - OVERTIME ) +
payRate * OVERTIME;
}
public:
void Print ()
{
CalcSalary();
cout << "ID
:
<< "Name
:
<< "Pay Rate:
<< "Hours
:
<< "Salary :
}
}
"
"
"
"
"
<<
<<
<<
<<
<<
employeeID << endl
firstName
<< " " << lastName
payRate
<< endl
weeklyHours << endl
weeklySalary << endl << endl;
<< endl
Class Method Modifier const
class Student
{
private:
long
id;
string firstName, lastName, major;
char
gender;
float gpa;
public:
// The method will NOT change any data members: const.
// It cannot call a non-const member functions!
void PrintRecord ()
{
cout << "Name :
<< "Gender:
<< "Major :
<< "GPA
:
}
const
"
"
"
"
<<
<<
<<
<<
firstName
gender
major
gpa
<<
<<
<<
<<
" " << lastName
endl
endl
endl;
<< endl
// The method will change some data members: no const.
void ReadRecord ()
{
cin >> id >> firstName >> lastName >> gender >> major >> gpa;
}
};
Class Method Modifier const
class Student
{
private:
long
id;
string firstName, lastName, major;
char
gender;
float gpa;
public:
void Write() const
float GetGPA() const
string GetFirst() const
// No const
void Read()
void SetGPA( float value )
void UpdateGPA( float amount )
. . .
};
Comparing Objects
Student stu1, stu2;
stu1.ReadRecord();
stu2.ReadRecord();
// Check if stu1’s GPA is higher than stu2
if ( stu1.GetGPA() > stu2.GetGPA() )
cout << stu1.GetFirstName()
<< " has higher GPA than "
<< stu2.GetFirstName()
<< endl;
Comparing Method
class Student
{
...
public:
// Use a Student object as a parameter!
bool HasHigherGPA ( Student stu ) const
{
return ( gpa > stu.gpa );
}
};
Pass Objects as Parameters
 Basic Data Types (char, int, float, string, bool)
Pass by Value (without & in prototype)
Pass by Reference (with & in prototype)
 Arrays (of any data type)
Always Pass by Reference
(Never &)
 Class Object (and structure)
C++ allows pass by value (no &) and by reference (&)
Our Rule: Always pass by reference with &
Use const for in parameter
Comparing Method
class Student
{
...
public:
// Pass by reference
// Use const to make sure stu will not be changed
bool HasHigherGPA ( const Student& stu ) const
{
return ( gpa > stu.gpa );
}
};
Re-Visit Copy Constructor
class Student
{
...
public:
// Copy constructor:
//
gets initial values from object s
// Will change data members: no const.
// Will not change parameter s: const with &
Student( const Student& stu )
{
id = stu.id;
firstName = stu.firstName;
lastName = stu.lastName;
gender = stu.gender;
major = stu.major;
gpa = stu.gpa;
}
...
};
More methods in StudentList
class StudentList
{
...
public:
int Find( const Student& stu ) const
int Find( long stuID ) const
int Find( string fName, string lName ) const
// Similar as multiple constructors, a class can also
// have multiple methods with the same name,
// but DIFFERENT parameters!
void GetStats( float& max, float& min, float& average ) const
void UpdateGPA ( long id, float gpa )
...
};
// See studentList3.cpp for details
Design your class
 What should be included in your class (Student)?
 treat your class as a real world entity.
 attributes related to the class: gpa, major, etc.
 operations that can be initiated by the class: read, write,
get, set, calculate, etc.
 For class Student, should “find”, “add”, “delete”, “sort”
be its methods?
 NO! They are not initiated and manageable by Student.
Summary
 class
 private and public members
 data fields and operations
 class constructor
 class objects


array of class objects
pass object as a function parameter
 class method modifier const
 class for a list
switch statement
const
const
const
const
const
float
float
float
float
float
A_GRADE
B_GRADE
C_GRADE
D_GRADE
F_GRADE
=
=
=
=
=
4.0;
3.0;
2.0;
1.0;
0.0;
char grade;
cin >> grade;
cout << endl << "Your grade is "
<< fixed << setprecision(1);
if ( grade == ‘A’)
cout << A_GRADE;
else if ( grade == ‘B’ )
cout << B_GRADE;
else if ( grade == ‘C’ )
cout << C_GRADE;
else if ( grade == ‘D’ )
cout << D_GRADE;
else if ( grade == ‘F’ )
cout << F_GRADE;
else
cout << “not valid!”;
char grade;
cin >> grade;
cout << endl << "Your grade is "
<< fixed << setprecision(1);
switch( grade )
{
case 'A': cout << A_GRADE;
break;
case 'B': cout << B_GRADE;
break;
case 'C': cout << C_GRADE;
break;
case 'D': cout << D_GRADE;
break;
case 'F': cout << F_GRADE;
break;
default : cout << "not valid!";
}
switch statement
 Syntax:
switch (IntegralOrEnumExpression)
{
case ConstantExpression: statement1
...
default: statementN
}
 switch, case and default are key words.
 break; is used to stop execution and go directly to the end of the
statement block. (optional)
C++ Data Types
simple
integral
enum
structured
floating
array struct union class
char short int long bool
float double long double
address
pointer reference
Store Student Records in Structure
struct Student
{
long
id;
string firstName;
string lastName;
char
gender;
string major;
float gpa;
};
// Now Student is a Data Type!
C++ Struct (Record)
 Syntax:
struct TypeName
{
MemberList;
};
 Struct is a heterogeneous structured data type:
 each individual component is called a field
 they can be of different data types
 Declare a struct
 before the function prototypes
 after the constant declarations
Everything needs to be declared before used!
Declare a Structure Student
const int MAX_STUDENTS = 100;
struct Student
{
long
id;
string firstName;
string lastName;
char
gender;
string major;
float gpa;
};
int ReadRecord ( int maxSize, Student record[] );
void OutputRecord ( long stuID, int size, const Student record[] );
int SearchID ( const Student record[], int size, long target );
int main()
{
Student stuRecord[MAX_STUDENTS];
//…
}
//Since Student is a data
type, we can also make an
array of Student!
Accessing Members of a Structure
 Use the dot notation.
Student stu1;
// Input data into struct
cout << "Enter ID: ";
cin >> stu1.id;
cout << "Enter first name: ";
cin >> stu1.firstName;
// Output student data
cout << setw(8) << stu1.id
<< setw(15)<< stu1.firstName;
Substitute Parallel Arrays with Structure: Read
//-------------------------------------------------------------// The function reads student records from an input file into different arrays and
// count the actual number of input records. Once the user input maxSize elements,
// the function will stop reading the input. It returns the actual number of records.
// Parameters: (in, out)
//-------------------------------------------------int ReadRecord ( int maxSize, Student record[] )
{
ifstream inData;
inData.open ( "student-record.in" );
int size = 0;
inData >> record[size].id >> record[size].firstName >>
>> record[size].gender >> record[size].major >>
while ( !inData.eof() && size < maxSize )
{
size ++;
inData >> record[size].id >> record[size].firstName
>> record[size].gender >> record[size].major
}
inData.close();
return size;
}
record[size].lastName
record[size].gpa;
>> record[size].lastName
>> record[size].gpa;
Substitute Parallel Arrays with Structure: Search
// Parameters: (in, in, in)
//-----------------------------------------------int SearchID ( const Student record[], int size, long target )
{
for ( int i = 0; i < size; i++ )
{
if ( record[i].id == target )
return i;
}
return -1;
}
Substitute Parallel Arrays with Structure: Output
//------------------------------------------------------------------// The function takes the student id and total number of records
// as inputs. If there exists a record with that student id,
// the function will print out the student's id, name, gender, major,
// and gpa; otherwise, it will print a "Not found" message.
// Parameters: ( in, in, in )
//------------------------------------------------------------------void OutputRecord ( long stuID, int size, const Student record[] )
{
int index;
index = SearchID ( record, size, stuID );
if ( index != -1 )
{
cout << "Name : " << record[index].firstName << " "
<< record[index].lastName << endl
<< "Gender: " << record[index].gender
<< endl
<< "Major : " << record[index].major
<< endl
<< "GPA
: " << record[index].gpa
<< endl;
}
else
cout << "The student record does not exist!" << endl;
}
Download