題目:
大學中的人員分三類 :學生,教師和職員,他們的基本信息如下:
學生:姓名,年齡,學號,年級,成績
教師:姓名,年齡,身份證號,職稱,工資
職員:姓名,年齡,身份證號,工資
現在需要管理各類人員的信息,請用面向對象的方法設計壹個異質鏈表,用來存放他們的信息。
/*異質鏈表實現:有三個類 student,teacher,staff,再定義壹個
鏈表類,此類用來存放這幾個不同類的對象,並將鏈表類 list 聲明為所有這些
類的友元,使它們可以訪問它們的私有成員。*/
#include <iostream.h>
#include <string.h>
#include <conio.h>
class person{ //定義壹個***同的基類,它具有公***的數據成員
friend class list; //鏈表類作為本類的友元
protected:
char name[20]; //定義姓名
int age; //定義年齡
char add[40]; //定義地址
char tele[20]; //定義電話號碼
static person *ptr; //定義壹個指向person類對象的靜態指針
person *next; //指向下壹個對象的指針
public:
person(char *name,int age,char *add,char *tele);//構造函數
virtual void print(); //說明虛函數
virtual void insert(){};//定義虛函數並且什麽也不做,只定義壹個接口
};
class student:public person{ //派生類 student
friend class list; //鏈表類作為本類的友元
int level; //定義年級
float grade_point_average; //定義平均分
public:
student(char *name,int age,char *add,char *tele, int level,
float grade_point_average); //聲明構造函數
void print(); //重新定義print()函數
void insert(); //重新定義insert()函數
};
//
class teacher:public person{ //派生類 teacher
friend class list; //鏈表類作為本類的友元
float salary; //定義工資
public:
teacher(char *name,int age,char *add,char *tele,float salary);
//聲明構造函數
void print(); //重新定義print()函數
void insert(); //重新定義insert()函數
};
//
class staff:public person{ //派生類 staff
friend class list; //鏈表類作為本類的友元
float hourly_wages; //定義計時工資
public:
staff(char *name,int age,char *add,char *tele,
float hourly_wages); //聲明構造函數
void print(); //重新定義print()函數
void insert(); //重新定義insert()函數
};
//
class list{ //定義異質鏈表類
person *root; //鏈表頭指針
public:
list(){ root=0; } //鏈表構造函數,初始為 0
void insert_person(person *node); //向鏈表插入壹個對象結點
void remove(char *name); //從鏈表移去壹個對象結點
void print_list(); //輸出整個鏈表
};
//
person::person(char *name,int age,char *add,char *tele)
{ //person 的構造函數
strcpy(person::name,name);
strcpy(person::add,add);
strcpy(person::tele,tele);
person::age=age;
next=0;
}
void person::print() //基類的虛成員函數print()版本,輸出基類數據成員
{
cout<<"\nname: "<<name<<"\n";
cout<<"age: "<<age<<"\n";
cout<<"address: "<<add<<"\n";
cout<<"telephone number: "<<tele<<"\n";
}
//
student::student(char *name,int age,char *add,char *tele, int level,
float grade_point_average):person(name,age,add,tele)
{ //student 派生類的構造函數,需綴上基類的構造函數
student::level=level;
student::grade_point_average=grade_point_average;
}
void student::print() //派生類 student的成員函數print()新版本
{
person::print();
cout<<"grade point average: "<<grade_point_average<<"\n";
}
void student::insert()
{ //將 student 類的壹個對象賦給 ptr 基類指針,這是允許的
ptr=new student(name,age,add,tele,level,grade_point_average);
}
//
teacher::teacher(char *name,int age,char *add,char *tele, float salary)
:person(name,age,add,tele) //teacher 派生類的構造函數,需綴上
//基類的構造函數
{
teacher::salary=salary;
}
void teacher::print() //派生類 teacher的成員函數print()新版本
{
person::print();
cout<<"salary: "<<salary<<"\n";
}
void teacher::insert()
{ //將 teacher類的壹個對象賦給 ptr 基類指針,這是允許的
ptr=new teacher(name,age,add,tele,salary);
}
//
staff::staff(char *name,int age,char *add,char *tele, float hourly_wages)
:person(name,age,add,tele) //staff 派生類的構造函數,需綴上
//基類的構造函數
{
staff::hourly_wages=hourly_wages;
}
void staff::print() //派生類 staff的成員函數print()新版本
{
person::print();
cout<<"hourly_wages: "<<hourly_wages<<"\n";
}
void staff::insert()
{ //將 staff類的壹個對象賦給 ptr 基類指針,這是允許的
ptr=new staff(name,age,add,tele,hourly_wages);
}
//
void list::insert_person(person *node)
{ //向異質鏈表插入壹個對象,可能是student或teacher或staff
char key[20];
strcpy(key,node->name); //將需插入的對象的姓名賦給key
person *curr_node=root;
person *previous=0; //定義二個查找指針
while(curr_node !=0 && strcmp(curr_node->name,key)<0)
{ //用 curr_node在前,previous在後及 key 循環查找插入位置,由 name
//字符串升序排序,strcmp(串1,串2)<0 表示串1<串2,繼續找
previous=curr_node;
curr_node=curr_node->next;
}
node->insert(); //由於 insert() 是虛函數,它會根據 node 指針的對象調
//用不同的版本:ptr=new <三個派生類名之壹>(數據成員變量表),
//而數據成員變量是由構造函數賦值的,由 new 特性: int *s;
// s=new int(20); 會開辟空間並把值20給空間,因此說:
//調用虛函數將待插入對象賦給 ptr 所指向的單元
node->ptr->next=curr_node;
if(previous==0)
root=node->ptr;
else
previous->next=node->ptr;
//以上三句是把 ptr 指的結點插入鏈中,這裏:node->ptr, previous->ptr,
//curr_node->ptr 統統都是壹樣的,即相當於 person::ptr 說明 ptr 受限的
//對象是stu::ptr或tea::ptr或sta::ptr,因此 node->ptr->next 可寫成
// (node->ptr)->next 或 person::ptr->next 但不能把 node->name 寫成
// person::name,它只能出現在構造函數中
}
void list::remove(char *name)
{ //從異質鏈表中移去壹對象,此對象用關鍵字 name 去匹配
person *curr_node=root;
person *previous=0;
while(curr_node !=0 && strcmp(curr_node->name,name)!=0)
{ //用循環尋找此對象
previous=curr_node;
curr_node=curr_node->next;
}
if(curr_node!=0 && previous==0) //若此對象為鏈表中的頭結點
{
root=curr_node->next;
delete curr_node;
}
else if(curr_node!=0 && previous!=0) //此對象為鏈表中的非頭結點
{
previous->next=curr_node->next;
delete curr_node;
}
}
void list::print_list()
{
person *cur=root; //先將頭指針賦給 cur
while(cur!=0) //循環輸出結點內容並移動指針
{
cur->print(); //根據 cur 所指向的對象不同調用不同的 print() 版本
cur=cur->next;
}
}
//
person *person::ptr=0; //為靜態變量賦初值
int main()
{
char c;
list people; //定義 list 類的對象 people ,同時調用 list 構造函數,
//也即 root=0;
student stu("劉影liuying",20,"上海shanghai","03578395-456",3,80.0);
//定義 student 類的對象 stu,同時調用 student 構造函數,
//也即先基類 person 構造函數,再自己
teacher tea("李明liming",35,"北京beijing","0105918695-106",560.50);
staff sta("陳林chenling",40,"青島qingdao","05325895944-335",10);
people.insert_person(&stu);
people.insert_person(&tea);
people.insert_person(&sta);
cout<<"插入結束!\n";
people.print_list();
cout<<"\n以上打印出原鏈表! 打 c <回車> 繼續....";
cin>>c;
people.remove("陳林chenling");
people.remove("李明liming");
people.remove("王迢wangchong");
cout<<"刪除結束!\n";
people.print_list();
cout<<"\n以上打印出刪除後鏈表!\n";
return 0;
}