#include <iostream>
using namespace std;
/*---------------------------------
链表使用例程
第19章代码重用 : 19.15~21.图书药品管理系统 19.24.包含与继承
1)date类只负责存放数据
2)node类只用来创建和操作节点
3)list类只用来创建和操作链表
4)Repair类只用来管理链表对象和显示程序主界面
注意:
1)派生类要继续派生时,最好使用公有继承。
2)假如不想让派生类访问基类的某个或某些成员时,不要使用公有继承,而应该使用
私有继承。
3)假如你在一个类中需要访问另一个类的多个对象时,必须使用包含,而不能
使用私有继承。
4)假如你想根据一个已有的类定义另一个类,并且希望在该类中可以访问已有类的
保护成员,那么请从已有类中派生此类,假如你只是想访问已有类的公有成员,不
想访问该类的保护成员,那么请使用类的包含。
---------------------------------*/
class date
{
public:
date(int num,float prc):number(num),price(prc)
{cout<<"构造date..."<<endl;}
float GetPrice()const{return price;}
int GetNumber()const{return number;}
virtual void print()const=0;
virtual ~date(){}
private:
int number;
float price;
};
class book:public date
{
public:
book(int num,float prc):date(num,prc) //子类的构造函数,初始化传递参数给父类的构造函数
{cout<<"构造book..."<<endl;}
virtual void print()const
{
cout<<"图书的编号:"<<GetNumber()<<endl;
cout<<"图书的价格:"<<GetPrice()<<endl;
}
private:
};
class drug:public date
{
public:
drug(int num,float prc):date(num,prc) //子类的构造函数,初始化传递参数给父类的构造函数
{cout<<"构造drug..."<<endl;}
virtual void print()const
{
cout<<"药品的编号:"<<GetNumber()<<endl;
cout<<"药品的价格:"<<GetPrice()<<endl;
}
private:
};
class node
{
public:
node(date* pdate):itsdate(pdate),itsnext(0){}
~node(){delete itsdate;itsdate=0;} //销毁对象数据
void SetNext(node* no){itsnext=no;}//记住下一个节点的地址
node* GetNext()const{return itsnext;}
date* Getdate()const
{
if(itsdate)
{ return itsdate;}
else
{ return NULL;}
}
private:
date* itsdate;
node* itsnext;
};
class list
{
public:
list():head(0),count(0){}
~list();
date* GetFirst()const;
date* operator[](int offset)const;
void show()const;
int GetCount()const{return count;}
void Insert(date*);
void Delete(int num);
date* Find(int num)const;
date* Find(int& place,int num)const;
private:
node* head;
int count;
};
list::~list()
{
node* l=head;
node* m=0;
int n=0;
while(l)
{
m=l;
l=l->GetNext();
delete m;
n++;
cout<<"删除第"<<n<<"个节点"<<endl;
}
}
date* list::GetFirst()const
{
if(head)
{ return head->Getdate();}
else
{ return NULL;}
}
date* list::operator[](int offset)const
{
node* pn=head;
if(!head)
{ return NULL;}
if(offset>=count)
{ return NULL;}
for(int i=0;i<offset;i++)
{
pn =pn->GetNext();
}
return pn->Getdate();
}
void list::show()const
{
if(!head)
{ return;}
node* pn=head;
do{
pn->Getdate()->print();//获取节点数据对象的地址后,打印相关数据
pn=pn->GetNext();
}while(pn);
}
void list::Insert(date* pdate)
{
node* pn=new node(pdate);
node* pnow=head;
node* pnext=0;
int num=pdate->GetNumber();
if(!pnow)
{
head=pn;
count=1;
return;
}
count++;
#if 0
//头部插入
pnext=head->GetNext();
pn->SetNext(pnext);
head->SetNext(pn);
#else
//升序插入
if(head->Getdate()->GetNumber() > num)
{
pn->SetNext(head);
head=pn;
return;
}
else
{
pnext=head->GetNext();
pnow=head;
while(pnext)
{
if(pnext->Getdate()->GetNumber() > num)
{
pnow->SetNext(pn);
pn->SetNext(pnext);
return;
}
else
{
pnow=pnext;
pnext=pnext->GetNext();
}
}
pnow->SetNext(pn);
return;
}
#endif
}
void list::Delete(int num)
{
node* pback=head;
node* pnow=head;
if(!head)
{
cout<<"没有数据可删除"<<endl;
}
else
{
while(pnow)
{
if(num==pnow->Getdate()->GetNumber())
{
pback->SetNext(pnow->GetNext());
if(pnow==head)//特别注意,如果是边界节点的情况
{
head=head->GetNext();
cout<<"删除头结点"<<endl;
}
delete pnow;
pnow =NULL;
count--;
cout<<"删除成功"<<endl;
return;
}
else
{
pback=pnow;
pnow=pnow->GetNext();
}
}
cout<<"没有该数据,无法删除!"<<endl;
}
}
date* list::Find(int num)const
{
node* pn=0;
for(pn=head;pn!=NULL;pn=pn->GetNext())
{
if(pn->Getdate()->GetNumber()==num)
break;
}
if(pn==NULL)
return NULL;
else
return pn->Getdate();
}
date* list::Find(int& place,int num)const
{
node* pn=0;
for(pn=head;pn!=NULL;pn=pn->GetNext(),place++)
{
if(pn->Getdate()->GetNumber()==num)
break;
}
if(pn==NULL)
return NULL;
else
return pn->Getdate();
}
#if 1
/*
19.23.利用私有继承来实现代码重用
1)包含和私有继承的区别:
包含是将一个已命名的对象添加到类的私有部分中,而私有继承则是将一个未
命名的对象(this对象)添加到类的私有部分中。
*/
class Repair:private list
{
public:
void RInsert(date* newdate);
void Run();
private:
};
void Repair::RInsert(date* newdate)
{
int number=newdate->GetNumber();
int place=0;
if(Find(place,number))
{ cout<<"您输入的编号"<<number<<"与链表中第"<<place<<"个节点的编号重复"<<endl;}
else //为空,没找到,则插入
{ Insert(newdate);}
}
void Repair::Run()
{
date* pdate=0;
int number;
float price;
int choice;
bool quit=false;
while(1)
{
//system("cls");
cout<<"1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出"<<endl;
cin>>choice;
switch(choice)
{
case 1:
while(1)
{
cout<<"0)返回 1)图书 2)药品:";
cin>>choice;
if(!choice)
{ break;}
else if(1==choice||2==choice)
{
cout<<"请输入编号:";
cin>>number;
if(1==choice)
{
cout<<"请输入图书价格:";
cin>>price;
pdate=new book(number,price);
RInsert(pdate);
}
else if(2==choice)
{
cout<<"请输入药品价格:";
cin>>price;
pdate=new drug(number,price);
RInsert(pdate);
}
else
{ cout<<"请输入0到2之间的数字!"<<endl;}
}
}
break;
case 2:
if(GetFirst()==0)
{
cout<<"您的商品为空,请增加商品\n按回车键返回";
cin.get();
cin.get();
}
else
{
show();
cout<<"请按回车键返回主界面"<<endl;
cin.get(); cin.get();
}
break;
case 3:
cout<<"请输入您要删除的商品编号:"<<endl;
cin>>number;
Delete(number);
cin.get(); cin.get();
break;
case 4:
while(1)
{
cout<<"0)返回 1)按编号查询 2)按序号查询:";
cin>>choice;
if(!choice)
{ break;}
else if(1==choice||2==choice)
{
if(1==choice)
{
cout<<"请输入要查询的编号:";
cin>>number;
date* result=Find(number);
if(NULL==result)
{ cout<<"找不到该编号的商品"<<endl;}
else
{ result->print();}
}
else if(2==choice)
{
cout<<"请输入要查找的序号(链表的节点脚标号):";
cin>>number;
if((*this)[number]) //用"*"读取this指针指向的this对象
{ (*this)[number]->print();}//与类的包含不同,类的私有继承需
else //要在这里显示地注明调用下标运算符的对象
{ cout<<"找不到该序号的商品"<<endl;}
}
else
{ cout<<"请输入0到2之间的数字!"<<endl;}
}
}
break;
case 5:
cout<<"该链表共有"<<GetCount()<<"个节点"<<endl;
break;
case 6:
quit=true;
break;
default: break;
}
if(quit)
{
cout<<"程序结束"<<endl;
break;
}
}
}
#else
/*19.22.利用类的包含来实现代码重用*/
class Repair
{
public:
void RInsert(date* newdate);
void Run();
private:
list pl;//类的包含
};
void Repair::RInsert(date* newdate)
{
int number=newdate->GetNumber();
int place=0;
if(pl.Find(place,number))
{ cout<<"您输入的编号"<<number<<"与链表中第"<<place<<"个节点的编号重复"<<endl;}
else //为空,没找到,则插入
{ pl.Insert(newdate);}
}
void Repair::Run()
{
date* pdate=0;
int number;
float price;
int choice;
bool quit=false;
while(1)
{
//system("cls");
cout<<"1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出"<<endl;
cin>>choice;
switch(choice)
{
case 1:
while(1)
{
cout<<"0)返回 1)图书 2)药品:";
cin>>choice;
if(!choice)
{ break;}
else if(1==choice||2==choice)
{
cout<<"请输入编号:";
cin>>number;
if(1==choice)
{
cout<<"请输入图书价格:";
cin>>price;
pdate=new book(number,price);
RInsert(pdate);
}
else if(2==choice)
{
cout<<"请输入药品价格:";
cin>>price;
pdate=new drug(number,price);
RInsert(pdate);
}
else
{ cout<<"请输入0到2之间的数字!"<<endl;}
}
}
break;
case 2:
if(pl.GetFirst()==0)
{
cout<<"您的商品为空,请增加商品\n按回车键返回";
cin.get();
cin.get();
}
else
{
pl.show();
cout<<"请按回车键返回主界面"<<endl;
cin.get(); cin.get();
}
break;
case 3:
cout<<"请输入您要删除的商品编号:"<<endl;
cin>>number;
pl.Delete(number);
cin.get(); cin.get();
break;
case 4:
while(1)
{
cout<<"0)返回 1)按编号查询 2)按序号查询:";
cin>>choice;
if(!choice)
{ break;}
else if(1==choice||2==choice)
{
if(1==choice)
{
cout<<"请输入要查询的编号:";
cin>>number;
date* result=pl.Find(number);
if(NULL==result)
{ cout<<"找不到该编号的商品"<<endl;}
else
{ result->print();}
}
else if(2==choice)
{
cout<<"请输入要查找的序号(链表的节点脚标号):";
cin>>number;
if(pl[number])
{ pl[number]->print();}
else
{ cout<<"找不到该序号的商品"<<endl;}
}
else
{ cout<<"请输入0到2之间的数字!"<<endl;}
}
}
break;
case 5:
cout<<"该链表共有"<<pl.GetCount()<<"个节点"<<endl;
break;
case 6:
quit=true;
break;
default: break;
}
if(quit)
{
cout<<"程序结束"<<endl;
break;
}
}
}
#endif
int main()
{
Repair A;
A.Run();
return 0;
}
运行结果:
1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出
1
0)返回 1)图书 2)药品:1
请输入编号:5
请输入图书价格:1.3
构造date...
构造book...
0)返回 1)图书 2)药品:2
请输入编号:2
请输入药品价格:10.2
构造date...
构造drug...
0)返回 1)图书 2)药品:2
请输入编号:2
请输入药品价格:12.3
构造date...
构造drug...
您输入的编号2与链表中第0个节点的编号重复
0)返回 1)图书 2)药品:3
0)返回 1)图书 2)药品:2
请输入编号:3
请输入药品价格:12.3
构造date...
构造drug...
0)返回 1)图书 2)药品:0
1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出
2
药品的编号:2
药品的价格:10.2
药品的编号:3
药品的价格:12.3
图书的编号:5
图书的价格:1.3
请按回车键返回主界面
1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出
4
0)返回 1)按编号查询 2)按序号查询:1
请输入要查询的编号:3
药品的编号:3
药品的价格:12.3
0)返回 1)按编号查询 2)按序号查询:2
请输入要查找的序号(链表的节点脚标号):3
找不到该序号的商品
0)返回 1)按编号查询 2)按序号查询:2
请输入要查找的序号(链表的节点脚标号):2
图书的编号:5
图书的价格:1.3
0)返回 1)按编号查询 2)按序号查询:0
1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出
2
药品的编号:2
药品的价格:10.2
药品的编号:3
药品的价格:12.3
图书的编号:5
图书的价格:1.3
请按回车键返回主界面
5
1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出
5
该链表共有3个节点
1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出
3
请输入您要删除的商品编号:
5
删除成功
1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出
2
药品的编号:2
药品的价格:10.2
药品的编号:3
药品的价格:12.3
请按回车键返回主界面
1)增加商品 2)列出所有商品 3)删除商品 4)查找商品 5)商品数目 6)退出
6
程序结束
删除第1个节点
删除第2个节点
Press any key to continue
C++ 代码重用 03-- 链表使用例程 类的包含与继承
最新推荐文章于 2021-05-03 21:07:39 发布