Array Index Out of Bounds

Chapter 19 - Working in an Object-oriented Environment

Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
  Copyright 1998 The McGraw-Hill Companies

An Object-oriented Linked List in C++
A linked-list program was developed in Chapter 14 using a traditional procedural programming approach in C++. When using the procedure-oriented approach, you learned that the linked-list program is difficult to alter and maintain. In this chapter, a linked-list program using objects is developed that will allow you to create a list of employee information. It will also be possible to add and delete employees from the list. To limit the size of the linked-list program, no user interface will be used for gathering employee data. Data for the linked list has been hardwired in the main( ) function. Examples of how to make this program interactive and able to accept information from the keyboard have been shown in earlier chapters.
This program is slightly more involved than the application presented in Chapter 14. It includes, in addition to linked-list concepts, all seven of the object-oriented concepts listed earlier.
Creating a Parent Class
Several child classes derived from a common parent class are used in this example. The parent class for this linked-list example is named NNR. Here, the letters NNR represent the Nineveh National Research Company that develops computer-related books and software. The linked-list program is a database that will keep pertinent information and payroll data on company employees. The purpose of the parent class NNR is to gather information common to all subsequent derived child classes. For this example, that common information includes an employee’s last name, first name, occupation title, social security number, and year hired at the company. The parent class NNR has three levels of isolation: public, protected, and private. The protected section of this class shows the structure for gathering data common to each derived child class. The public section (member functions) shows how that information will be intercepted from the function main( ).
// PARENT CLASS
class NNR {

friend class payroll_list;

protected:
 char lstname[20];
 char fstname[15];
 char job_title[30];
 char social_sec[12];
 double year_hired;
 NNR *pointer;
 NNR *next_link;
public:
 NNR(char *lname,char *fname,char *ss,
     char *job,double y_hired)
 {
   strcpy(lstname,lname);
   strcpy(fstname,fname);
   strcpy(social_sec,ss);
   strcpy(job_title,job);
   year_hired=y_hired;
   next_link=0;
 }
    .
    .
    .
    .
A friend class named payroll_list is used by the parent class and all derived child classes. When you study the full program listing in the section entitled “Examining the Complete Program” later in this chapter, notice that all derived child classes share this common variable, too. (Remember how the terms “private” and “public” relate to encapsulation concepts used by object-oriented programmers.)
A Derived Child Class
Four derived child classes are used in this program. Each of these is derived from the parent class NNR shown in the last section. This segment presents one child class, salespersons, which represents the points common to all four derived classes. A portion of this derived class is shown next. The derived child class satisfies the object-oriented concept of inheritance.
//SUB OR DERIVED CHILD CLASS
class salespersons:public NNR {

friend class payroll_list;

private:
 double disk_sales;
 double comm_rate;
public:
 salespersons(char *lname,char *fname,char *ss,
              char *job,double y_hired,
              double d_sales,double c_rate):
              NNR(lname,fname,ss,
              job,y_hired)
 {
   disk_sales=d_sales;
   comm_rate=c_rate;
 }
    .
    .
    .
    .
The salespersons child class gathers information and adds it to the information already gathered by the parent class. This in turn forms a data structure composed of last name, first name, social security number, year hired, the total sales, and the appropriate commission rate.
Here is the remainder of the child class description:
    .
    .
    .
    .

 void fill_sales(double d_sales)
 {
   disk_sales=d_sales;
 }

 void fill_comm_rate(double c_rate)
 {
   comm_rate=c_rate;
 }
 void add_info( )
 {
   pointer=this;
 }

 void send_info( )
 {
   NNR::send_info( );
   cout << “\n Sales (disks): ” << disk_sales;
   cout << “\n Commission Rate: ” << comm_rate;
 }

};
Instead of add_info( ) setting aside memory for each additional linked-list node by using the new free store operator, the program uses each object’s this pointer. The pointer is being assigned the address of an NNR node.
Output information on a particular employee is constructed in a unique manner. In the case of the salespersons class, notice that send_info( ) makes a request to NNR‘s send_info( ) function. NNR‘s function prints the information common to each derived class; then the salespersons’ send_info( ) function prints the information unique to the particular child class. For this example, this information includes the sales and the commission rate.
It would also have been possible to print the information about the salesperson completely from within the child class, but the method used allows another advantage of object-oriented programming to be illustrated, and that is the use of virtual functions.
Using a Friend Class
The friend class, payroll_list, contains the means for printing the linked list and for the insertion and deletion of employees from the list. Here is a small portion of this class:
//FRIEND CLASS
class payroll_list {

private:
 NNR *location;

public:
 payroll_list( )
 {
   location=0;
 }
 void print_payroll_list( );

 void insert_employee(NNR *node);

 void remove_employee_id(char *social_sec);

};
    .
    .
    .
    .
Notice that messages that are sent to the member functions print_payroll_list( ), insert_employee( ), and remove_employee_id( ) form the functional part of the linked-list program.
Consider the function print_payroll_list( ), which begins by assigning the pointer to the list to the pointer variable present. While the pointer present is not zero, it will continue to point to employees in the linked list, direct them to send_info, and update the pointer until all employees have been printed. The next section of code shows how this is achieved:
    .
    .
    .
    .
void payroll_list::print_payroll_list( )
{
 NNR *present=location;

 while(present!=0) {
   present->send_info( );
   present=present->next_link;
 }
}
    .
    .
    .
The fact that the variable pointer contains the memory address of nodes inserted via add_info( ) was discussed earlier. This value is used by insert_employee( ) to form the link with the linked list. The insertion technique inserts data alphabetically by an employee’s last name. Thus, the linked list is always ordered alphabetically by last name.
A correct insertion is made by the application by comparing the last name of a new employee with those already in the list. When a name (node->lstname) already in the list is found that is greater than the current_node->lstname, the first while loop ends. This is a standard linked-list insert procedure that leaves the pointer variable, previous_node, pointing to the node behind where the new node is to be inserted and leaves current_node pointing to the node that will follow the insertion point for the new node.
Once the insertion point is determined, the program creates a new link or node by calling node->add_info( ). The current_node is linked to the new node’s next_link. The last decision that must be made is whether or not the new node is to be placed as the front node in the list or between existing nodes. The program establishes this by examining the contents of the pointer variable previous_node. If the pointer variable is zero, it cannot be pointing to a valid previous node, so location is updated to the address of the new node. If previous_node contains a nonzero value, it is assumed to be pointing to a valid previous node. In this case, previous_node->next_link is assigned the address of the new node’s address, or node->pointer.
    .
    .
    .
    .
void payroll_list::insert_employee(NNR *node)
{
 NNR *current_node=location;
 NNR *previous_node=0;

 while (current_node != 0 &&
        strcmp(current_node->lstname,node->lstname) < 0) {
   previous_node=current_node;
   current_node=current_node->next_link;
 }
 node->add_info( );
 node->pointer->next_link=current_node;
 if (previous_node==0)
   location=node->pointer;
 else
   previous_node->next_link=node->pointer;
}
    .
    .
    .
    .
Items can be removed from the linked list only by knowing the employee’s social security number. This technique adds a level of protection against accidentally deleting an employee.
As you examine remove_employee_id( ), shown in the next listing, note that the structure used for examining the nodes in the linked list is almost identical to that of insert_employee( ). However, the first while loop leaves the current_node pointing to the node to be deleted, not the node after the one to be deleted.
    .
    .
    .
    .
void payroll_list::remove_employee_id(char *social_sec)
{
 NNR *current_node=location;
 NNR *previous_node=0;

 while(current_node != 0 &&
       strcmp(current_node->social_sec,
       social_sec) != 0) {
   previous_node=current_node;
   current_node=current_node->next_link;
 }

 if(current_node != 0 && previous_node == 0) {
   location=current_node->next_link;
   delete current_node;
 }

 else if(current_node != 0 && previous_node != 0) {
   previous_node->next_link=current_node->next_link;
   delete current_node;
 }
}
The first compound if statement takes care of deleting a node in the front of the list. The program accomplishes this by examining the contents of previous_node to see if it contains a zero. If it does, then the front of the list, location, needs to be updated to the node following the one to be deleted. This is achieved with the following line:
current_node->next_link
The second if statement takes care of deleting a node between two existing nodes. This requires the node behind to be assigned the address of the node after the one being deleted.
previous_node->next_link=current_node->next_link.
Now that the important pieces of the program have been examined, the next section puts them together to form a complete program.
Examining the Complete Program
The following listing is the complete operational object-oriented linked-list program. The only thing it lacks is an interactive user interface. When the program is executed, it will add nine employees, with their different job titles, to the linked list and then print the list. Next, the program will delete two employees from the list. This is accomplished by supplying their social security numbers. The altered list is then printed. The main( ) function contains information on which employees are added and deleted.
//
//  nnr.cpp
//  C++ program illustrates object-oriented programming
//  with a linked list. This program keeps track of
//  employee data at Nineveh National Research (NNR).
//  Copyright (c) Chris H. Pappas and William H. Murray, 1998
//
#include <iostream.h>
#include <string.h>

// PARENT CLASS
class NNR {

friend class payroll_list;

protected:
 char lstname[20];
 char fstname[15];
 char job_title[30];
 char social_sec[12];
 double year_hired;
 NNR *pointer;
 NNR *next_link;
public:
 NNR(char *lname,char *fname,char *ss,
     char *job,double y_hired)
 {
   strcpy(lstname,lname);
   strcpy(fstname,fname);
   strcpy(social_sec,ss);
   strcpy(job_title,job);
   year_hired=y_hired;
   next_link=0;
 }

 NNR( )
 {
   lstname[0]=NULL;
   fstname[0]=NULL;
   social_sec[0]=NULL;
   job_title[0]=NULL;
   year_hired=0;
   next_link=0;
 }

 void fill_lstname(char *l_name)
 {
   strcpy(lstname,l_name);
 }
 void fill_fstname(char *f_name)
 {
   strcpy(fstname,f_name);
 }

 void fill_social_sec(char *soc_sec)
 {
   strcpy(social_sec,soc_sec);
 }

 void fill_job_title(char *o_name)
 {
   strcpy(job_title,o_name);
 }

 void fill_year_hired(double y_hired)
 {
   year_hired=y_hired;
 }

 virtual void add_info( ) {
 }
 virtual void send_info( )
 {
   cout << “\n\n” << lstname << “, ” << fstname
     << “\n Social Security: #” << social_sec;
   cout << “\n Job Title: ” << job_title;
   cout << “\n Year Hired: ” << year_hired;
 }

};

//SUB OR DERIVED CHILD CLASS
class administration:public NNR {

friend class payroll_list;

private:
 double yearly_salary;

public:
 administration(char *lname,char *fname,char *ss,
                char *job,double y_hired,
                double y_salary):
                NNR(lname,fname,ss,
                job,y_hired)
 {
   yearly_salary=y_salary;
 }

 administration( ):NNR( )
 {
   yearly_salary=0.0;
 }

 void fill_yearly_salary(double salary)
 {
   yearly_salary=salary;
 }

 void add_info( )
 {
   pointer=this;
  }

 void send_info( )
 {
   NNR::send_info( );
   cout << “\n Yearly Salary: $” << yearly_salary;
 }

};

//SUB OR DERIVED CHILD CLASS
class salespersons:public NNR {

friend class payroll_list;

private:
 double disk_sales;
 double comm_rate;

public:
 salespersons(char *lname,char *fname,char *ss,
              char *job,double y_hired,
              double d_sales,double c_rate):
              NNR(lname,fname,ss,
              job,y_hired)
 {
   disk_sales=d_sales;
   comm_rate=c_rate;
 }

 salespersons( ):NNR( )
 {
   disk_sales=0.0;
   comm_rate=0;
 }

 void fill_sales(double d_sales)
 {
   disk_sales=d_sales;
 }
 void fill_comm_rate(int c_rate)
 {
   comm_rate=c_rate;
 }

 void add_info( )
 {
   pointer=this;
 }

 void send_info( )
 {
   NNR::send_info( );
   cout << “\n Sales (disks): ” << disk_sales;
   cout << “\n Commission Rate: ” << comm_rate;
 }

};

//SUB OR DERIVED CHILD CLASS
class technicians:public NNR {

friend class payroll_list;

private:
 double hourly_salary;

public:
 technicians(char *lname,char *fname,char *ss,char *job,
             double y_hired,double h_salary):
             NNR(lname,fname,ss,job,y_hired)
 {
   hourly_salary=h_salary;
 }

 technicians( ):NNR( )
 {
   hourly_salary=0.0;
 }

 void fill_hourly_salary(double h_salary)
 {
   hourly_salary=h_salary;
 }

 void add_info( )
 {
   pointer=this;
 }

 void send_info( )
 {
   NNR::send_info( );
   cout << “\n Hourly Salary: $” << hourly_salary;
 }

};

//SUB OR DERIVED CHILD CLASS
class supplies:public NNR {

friend class payroll_list;

private:
 double hourly_salary;

public:
 supplies(char *lname,char *fname,char *ss,char *job,
          double y_hired,double h_salary):
          NNR(lname,fname,ss,
          job,y_hired)
 {
   hourly_salary=h_salary;
 }

 supplies( ):NNR( )
 {
   hourly_salary=0.0;
 }

 void fill_hourly_salary(double h_salary)
 {
   hourly_salary=h_salary;
 }

 void add_info( )
 {
   pointer=this;
 }

 void send_info( )
 {
   NNR::send_info( );
   cout << “\n Hourly Salary: $” << hourly_salary;
 }

};

//FRIEND CLASS
class payroll_list {

private:
 NNR *location;

public:
 payroll_list( )
 {
   location=0;
 }

 void print_payroll_list( );

 void insert_employee(NNR *node);

 void remove_employee_id(char *social_sec);

};

void payroll_list::print_payroll_list( )
{
 NNR *present=location;

 while(present!=0) {
   present->send_info( );
   present=present->next_link;
 }
}

void payroll_list::insert_employee(NNR *node)
{
 NNR *current_node=location;
 NNR *previous_node=0;
 while (current_node != 0 &&
        strcmp(current_node->lstname,node->lstname) < 0) {
   previous_node=current_node;
   current_node=current_node->next_link;
 }
 node->add_info( );
 node->pointer->next_link=current_node;
 if (previous_node==0)
   location=node->pointer;
 else
   previous_node->next_link=node->pointer;
}

void payroll_list::remove_employee_id(char *social_sec)
{
 NNR *current_node=location;
 NNR *previous_node=0;

 while(current_node != 0 &&
    strcmp(current_node->social_sec,social_sec) != 0) {
   previous_node=current_node;
   current_node=current_node->next_link;
 }

 if(current_node != 0 && previous_node == 0) {
   location=current_node->next_link;
   // delete current_node; needed if new( ) used in add_info( )
 }
 else if(current_node != 0 && previous_node != 0) {
   previous_node->next_link=current_node->next_link;
   // delete current_node; needed if new( ) used in add_info( )
 }
}

main( )
{
 payroll_list workers;

 // static data to add to linked list
 salespersons salesperson1(“Harddrive”,"Harriet","313-56-7884",
                           “Salesperson”,1985,6.5,7.5);
 salespersons salesperson2(“Flex”,"Frank","663-65-2312",
                           “Salesperson”,1985,3.0,3.2);
 salespersons salesperson3(“Ripoff”,"Randle","512-34-7612",
                           “Salesperson”,1987,9.6,6.8);
 technicians techperson1(“Align”,"Alice","174-43-6781",
                           “Technician”,1989,12.55);
 technicians techperson2(“Tightscrew”,"Tom","682-67-5312",
                           “Technician”,1992,10.34);
 administration vice_president1(“Stuckup”,"Stewart",
                           “238-18-1119",”Vice President",
                            1980,40000.00);
 administration vice_president2(“Learnedmore”,"Lawrence",
                           “987-99-9653",”Vice President",
                            1984,45000.00);
 supplies supplyperson1(“Allpart”,"Albert","443-89-3772",
                           “Supplies”,1983,8.55);
 supplies supplyperson2(“Ordermore”,"Ozel","111-44-5399",
                           “Supplies”,1988,7.58);
 // add the nine workers to the linked list
 workers.insert_employee(&techperson1);
 workers.insert_employee(&vice_president1);
 workers.insert_employee(&salesperson1);
 workers.insert_employee(&supplyperson1);
 workers.insert_employee(&supplyperson2);
 workers.insert_employee(&salesperson2);
 workers.insert_employee(&techperson2);
 workers.insert_employee(&vice_president2);
 workers.insert_employee(&salesperson3);

 // print the linked list
 workers.print_payroll_list( );

 // remove two workers from the linked list
 workers.remove_employee_id(“238-18-1119");
 workers.remove_employee_id(”512-34-7612");

 cout << “\n\n***********************************”;

 // print the revised linked list
 workers.print_payroll_list( );

 return (0);
}
As you study the complete listing, see if you understand how employees are inserted and deleted from the list. If it is still a little confusing, go back and study each major section of code discussed in earlier sections.
Output from the Linked List
The linked-list program sends output to the monitor. The first section of the list contains the nine employee names that were used to create the original list. The last part of the list shows the list after two employees are deleted. Here is a sample output sent to the screen:
Align, Alice
Social Security: #174-43-6781
Job Title: Technician
Year Hired: 1989
Hourly Salary: $12.55

Allpart, Albert
Social Security: #443-89-3772
Job Title: Supplies
Year Hired: 1983
Hourly Salary: $8.55

Flex, Frank
Social Security: #663-65-2312
Job Title: Salesperson
Year Hired: 1985
Sales (disks): 3
Commission Rate: 3.2
Harddrive, Harriet
Social Security: #313-56-7884
Job Title: Salesperson
Year Hired: 1985
Sales (disks): 6.5
Commission Rate: 7.5

Learnedmore, Lawrence
Social Security: #987-99-9653
Job Title: Vice President
Year Hired: 1984
Yearly Salary: $45000

Ordermore, Ozel
Social Security: #111-44-5399
Job Title: Supplies
Year Hired: 1988
Hourly Salary: $7.58

Ripoff, Randle
Social Security: #512-34-7612
Job Title: Salesperson
Year Hired: 1987
Sales (disks): 9.6
Commission Rate: 6.8

Stuckup, Stewart
Social Security: #238-18-1119
Job Title: Vice President
Year Hired: 1980
Yearly Salary: $40000

Tightscrew, Tom
Social Security: #682-67-5312
Job Title: Technician
Year Hired: 1992
Hourly Salary: $10.34

***********************************
Align, Alice
Social Security: #174-43-6781
Job Title: Technician
Year Hired: 1989
Hourly Salary: $12.55

Allpart, Albert
Social Security: #443-89-3772
Job Title: Supplies
Year Hired: 1983
Hourly Salary: $8.55

Flex, Frank
Social Security: #663-65-2312
Job Title: Salesperson
Year Hired: 1985
Sales (disks): 3
Commission Rate: 3.2
Harddrive, Harriet
Social Security: #313-56-7884
Job Title: Salesperson
Year Hired: 1985
Sales (disks): 6.5
Commission Rate: 7.5

Learnedmore, Lawrence
Social Security: #987-99-9653
Job Title: Vice President
Year Hired: 1984
Yearly Salary: $45000

Ordermore, Ozel
Social Security: #111-44-5399
Job Title: Supplies
Year Hired: 1988
Hourly Salary: $7.58

Tightscrew, Tom
Social Security: #682-67-5312
Job Title: Technician
Year Hired: 1992
Hourly Salary: $10.34
More OOPs
We’re sure your interest in object-oriented has increased after working through this chapter. You will really be interested in the Windows applications developed in Chapters 22 through 26. These particular Windows applications make use of Microsoft’s Foundation Class (MFC) library. This library contains the reusable classes that make programming under Windows 95, 98, and NT much easier. As you study these chapters, you will see the concepts you have mastered in this chapter applied to the Windows environment.

Books24x7.com, Inc 2000 –  


Visual C++ 6(c) The Complete Reference
Visual Studio 6: The Complete Reference
ISBN: B00007FYGA
EAN: N/A
Year: 1998
Pages: 207

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net