您的位置:首页 > 编程语言

第十九章 19 利用私有继承来实现代码重用

2012-09-30 10:23 831 查看
//19 利用私有继承来实现代码重用
//我们还有一种方法来实现这种包含式的代码重用,那就是私有继承,派生类从基类私有继承后,其类的公有成员和保护成员在派生类中都是私有成员,私有成员成为不可访问的成员,这意味着我们必须在派生类中定义一个公有的成员函数,才能访问从基类中继承而来的成员函数,这与一个类的私有区域中包含另一个类的对像是实现思想是一致的
/*
#include <iostream>
#include <limits>
using namespace std;
class Date
{
public:
Date(int n, float p):number(n),price(p){}
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 n, float p):Date(n,p){}
virtual void print()const //定义纯虚函数
{
cout<<"图书的编号为:"<<GetNumber()<<endl;
cout<<"图书的价格为:"<<GetPrice()<<endl;
}
private:
};

class Drug:public Date
{
public:
Drug(int n, float p):Date(n,p){}
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*node){ itsNext = node; }  //设置下个节点
//获取下个节点的地址
Node *GetNext()const{ return itsNext; }
//获取当前地址对像的地址
Date *GetDate()const{
if(itsDate){
return itsDate;
}else{
return NULL;
}
}
private:
Date*itsDate; //当前数据
Node*itsNext; //下一个节点
};

//list链表类
class List
{
public:
List():head(0),count(0){}
~List(); //删除所有节点
Date *GetFirst()const;
Date *operator[](int)const; //重载下标运算符
void show()const; //输出所有节点数
int GetCount()const{ return count;} //取得节点数目

void InSert(Date*);//插入节点

void Delete(int number); //节点编号指的是商品的编号

Date*Find(int number)const; //查找数据

Date*Find(int &increase, int number)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();
}while(pn = pn->GetNext());
}

void List::InSert(Date *pDate)
{
Node *pn = 	new Node(pDate);
Node *pNow = head;
Node *pNext = 0;  //当前节点的下一个节点的地址,实始化为0
int New=pDate->GetNumber(); //取得商品编号
int next = 0; //下一个节点的商品编号
count++;
if(!head){ //设置头节点,判断头节点是否存在
head = pn;
return;
}
//头节点的数据的number值是否大于新节点的编号
if(head->GetDate()->GetNumber() > New){ //将新节点设置为头节点,头节点成为了新节点的下一个节点
pn->SetNext(head); //将新节点的下一个节点设置为头节点
head = pn;         //将来pn设置的新节点设置为新节点
return;
}
for(;;)
{
//当前节点的next指针是否为空,也就是有没有下一个指针对
if(!pNow->GetNext()){
pNow->SetNext(pn); //将新节点设置为下一个节点
return;
}
pNext = pNow->GetNext(); //当前节点还有下一个节点,那么获取当前节点的下一个节点
next = pNext->GetDate()->GetNumber(); //取得下一个节点的number值
if(next > New){ //当前节点的下一个节点的编号,与新节点的编号相对比
pNow->SetNext(pn);//当前节点的下一个节点设置为新节点
pn->SetNext(pNext); //用pn指向的下一个节点的设置为当前节点的下一个节点
return;
}
pNow = pNext; //如果没有找到相应的位置,那么将当前节点的下一个节点设置为当前节点
}
}
//删除函数
void List::Delete(int number)
{
Node *pBack=head; //保存上一个节点的地址,初始化的地址为头节点的地址
Node *pNow=head;  //当前节点,初始化为头节点的地址
if(!head){
cout<<"没有数据可删除!"<<endl;
return;
}
//如果是删除的是头节点
if(head->GetDate()->GetNumber() == number)
{
//判断头节点下面是否还有节点
if(!head->GetNext()){ //不存在下一个节点
delete head;
cout<<"数据被清空!"<<endl;
head=0;
count--; //数目减一
return;
}else{ //如果头节点有子节点
head = head->GetNext();
delete pNow;
pNow =0;
cout<<"删除成功!"<<endl;
count--;
return;
}
}

while(pBack)
{
if(pBack->GetNext() == NULL){ //没有下一个节点
cout<<"找不到要删除的编号"<<endl;
return;
}
if(pBack->GetNext()->GetDate()->GetNumber() == number)
{
pNow = pBack->GetNext();
pBack->SetNext(pNow->GetNext()); //头节点和被删除节点的下一个节点相联起来
delete pNow;
cout<<"删除数据成功!"<<endl;
pNow = 0;
count--;
return;
}
pBack = pBack->GetNext();
}
cout<<"不存在此编号数据"<<endl;
};

//查找节点
Date* List::Find(int number)const
{
Node* pn = 0; //来保存每个节点的地址
//cout<<"List::Find:"<<endl;
for(pn=head; pn!=NULL; pn=pn->GetNext())
{
//cout<<"pn->GetDate()->GetNumber():"<<pn->GetDate()->GetNumber()<<"="<<number<<endl;
if(pn->GetDate()->GetNumber() == number)
{
break;
}
}
if(pn==NULL){
return NULL;
}else{
return pn->GetDate();
}
return NULL;
}

Date*List::Find(int &increase, int number)const
{
Node*pn=0;
//cout<<"List::Find"<<endl;
for(pn=head, increase=0;  pn!=NULL; pn=pn->GetNext(), increase++)
{
if(pn->GetDate()->GetNumber() == number){
break;
}
}
if(pn == NULL){
return NULL;
}else{
return pn->GetDate();
}
return NULL;
}

class Repair : private List
{
public:
void RInsert(Date*newdate);
void Ran();
private:
//List pl;
};

void Repair::Ran()
{
//List pl;
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)药品"<<endl;
cin>>choice;
if(!choice){
break;
}else if(choice==1 || choice==2){
cout<<"请输入编号"<<endl;
cin>>number;
if(choice==1){
cout<<"请输入图书价格"<<endl;
cin>>price;
pDate = new Book(number,price);
//pl.InSert(pDate);
RInsert(pDate);
}else if(choice==2) {
cout<<"请输入药品价格"<<endl;
cin>>price;
pDate = new Drug(number,price);
//pl.InSert(pDate);
RInsert(pDate);
}else{
cout<<"请输入0到2之间的数字"<<endl;
}
}
}
break;
case 2: //例出所有商品
if(GetFirst()==0)
{
cout<<"您的商品为空,请增加商品"<<endl;
cout<<"按回车键返回主窗口"<<endl;
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)按序号进行查询"<<endl;
cin>>choice;
if(!choice){
break;
}else if(choice==1 || choice==2){
if(choice==1){
cout<<"请输入所有查找的商品编号"<<endl;
cin>>number;
Date*result = Find(number);
if(result==0){
cout<<"找不到该编号"<<endl;
}else{
result->print();//print是虚函数,可以去动态
}
}else if(choice==2) {
cout<<"请输入所要查找的数据的序号:"<<endl;
cin>>number;
if((*this)[number-1])
{
(*this)[number-1]->print();
}else{
cout<<"找不到你要查询的数据"<<endl;
}
}else{
cout<<"请输入0到2之间的数字"<<endl;
}
}
}
break;
case 5: //统计代码
cout<<"该链表共有"<<GetCount()<<"节点"<<endl;
cin.get();
cin.get();
break;
case 6://退出
quit = true;
break;
default:
cin.clear(); //用来清除cin的错误状态
//清空输入缓冲区中 numeric_limits<streamsize>::max()返回缓冲区的大小
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout<<"您只可以输入1-6之间的数字,请重新输入"<<endl;
cout<<"请按回输键返回并重新输入"<<endl;
cin.get();
cin.get();
break;
}
if(quit){
cout<<"程序结束"<<endl;
break;
}
}
}

void Repair::RInsert(Date*newdate)
{
int num = newdate->GetNumber();
int place =0; //查找数据的次数
cout<<"num:"<<num<<endl;
if(Find(place,num))
{
cout<<"您输入的编号"<<num<<"与链表中"<<endl;
cout<<"第"<<place+1<<"的编号重复"<<endl;
}else{
InSert(newdate);
}
}

int main()
{
Repair rp;
rp.Ran();
return 0;
}
*/


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐