C++编程题继承与多态

采用纯虚函数实现多态性来建立通用的双向链表派生类。

解:

#include<iostream>

using namespace std;

//首先看结点组织,采用结点类加数据类

class Object{//数据类为抽象类

public:

        Object(){}

        virtual bool operator>(Object &)=0;//纯虚函数,参数必须为引用或指针

        virtual bool operator!=(Object &)=0;//纯虚函数,参数必须为引用或指针

        virtual void Print()=0;//纯虚函数

        virtual ~Object(){} //析构函数可为虚函数,构造函数不行

};

class DblNode{

        Object* info;     //数据域用指针指向数据类对象

        DblNode *llink,*rlink;    //前驱(左链)、后继(右链)指针

public:

        DblNode(); //生成头结点的构造函数

    ~DblNode();

        void Linkinfo(Object* obj);

        friend class DblList;

        //DblList为友元类,DblList可直接访问DblNode的私有函数,与结构一样方便,但更安全

};

DblNode::DblNode(){info=NULL;llink=rlink=NULL;}

DblNode::~DblNode(){

        cout<<"删除结点类"<<'\t';

        delete info;     //释放数据域

}

void DblNode::Linkinfo(Object * obj){info=obj;}

//再定义双链表类,选择常用操作

class DblList{

        DblNode *head,*current;

public:

        DblList();//构造函数,生成头结点(空链表)

        ~DblList();//析构函数

        void MakeEmpty();//清空链表,只余表头结点

        void InsertFront(DblNode* p);      //可用来向前生成链表,在表头插入一个结点

        void InsertRear(DblNode* p);       //可用来向后生成链表,在表尾添加一个结点

        void InsertOrder(DblNode* p);  //按升序生成链表

        DblNode* CreatNode();//创建一个结点(孤立结点)

        DblNode* DeleteNode(DblNode* p);        //删除指定结点

        void PrintList();//打印链表的数据域

        int Length();//计算链表长度

        DblNode *Find(Object & obj);//搜索数据域与定值相同的结点,返回该结点的地址

        //其它操作

};

DblList::DblList(){//建立表头结点

        head=new DblNode();

        head->rlink=head->llink=head;

        current=NULL;

}

DblList::~DblList(){

        MakeEmpty();//清空链表

        cout<<"删除头结点:";

        delete head;

}

void DblList::MakeEmpty(){

        DblNode *tempP;

        while(head->rlink!=head){

                tempP=head->rlink;

                head->rlink=tempP->rlink;//把头结点后的第一个节点从链中脱离

                tempP->rlink->llink=head;//处理左指针

                delete tempP;           //删除(释放)脱离下来的结点

        }

        current=NULL;  //current指针恢复

}

void DblList::InsertFront(DblNode *p){

        p->llink=head;//注意次序

        p->rlink=head->rlink;

        head->rlink->llink=p;

        head->rlink=p;//最后做

}

void DblList::InsertRear(DblNode *p){

        p->rlink=head;//注意次序

        p->llink=head->llink;

        head->llink->rlink=p;

        head->llink=p;//最后做

}

void DblList::InsertOrder(DblNode* p){

        if(head==head->llink) {

                p->llink=head;//注意次序

                p->rlink=head->rlink;

                head->rlink->llink=p;

                head->rlink=p;//最后做

        }

        else{

                current=head->rlink;

                while(current!=head){

                        if(*current->info>*p->info) break; //找第一个比插入结点大的结点

                        current=current->rlink;

                }

                p->rlink=current;//注意次序

                p->llink=current->llink;

                current->llink->rlink=p;

                current->llink=p;//最后做

        }

}

DblNode* DblList::CreatNode(){//建立新节点

        current=new DblNode();

        return current;

}

DblNode* DblList::DeleteNode(DblNode* p){

        current=head->rlink;

        while(current!=head&&current!=p) current=current->rlink;

        if(current==head) current=NULL;

        else{//结点摘下

                p->llink->rlink=p->rlink;

                p->rlink->llink=p->llink;

                p->rlink=p->llink=NULL;

        }

        return current;

}

DblNode* DblList::Find(Object & obj){//对抽象类只能用引用

        current=head->rlink;

        while(current!=head&&*current->info!=obj) current=current->rlink;

        if(current==head) current=NULL;

        return current;//搜索成功返回该结点地址,不成功返回NULL

}

void DblList::PrintList(){

        current=head->rlink;

        while(current!=head){

                current->info->Print();

                current=current->rlink;

        }

        cout<<endl;

}

DblList::Length(){

        int count=0;

        current=head->rlink;

        while(current!=head){

                count++;

                current=current->rlink;

        }

        return count;

}

//ep8_9.cpp

#include "ep8_9.h"

#include<string>

using namespace std;

class StringObject:public Object{

        string sptr;

public:

        StringObject();

        StringObject(string);

        ~StringObject();

        bool StringObject::operator>(Object & obj);//虚函数

        bool StringObject::operator!=(Object & obj);//虚函数

        void Print();

};

StringObject::StringObject(){sptr="";}

StringObject::StringObject(string s){sptr=s;}

StringObject::~StringObject(){cout<<"删除字符串类"<<endl;}

bool StringObject::operator>(Object & obj){//虚函数

        StringObject & temp=(StringObject &)obj;//必须转换

        return sptr>temp.sptr;

}

bool StringObject::operator!=(Object & obj){//虚函数

        StringObject & temp=(StringObject &)obj;//必须转换

        return sptr!=temp.sptr;

}

void StringObject::Print(){cout<<sptr<<'\t';}//虚函数

int main(){

        DblNode * P1;

        StringObject* p;

        DblList list1,list2,list3;

        char *a[5]={"dog","cat","bear","sheep","ox"},*sp="cat";

        int i;

        for(i=0;i<5;i++){

                p=new StringObject(a[i]);//建立数据对象

                P1=list1.CreatNode();//建立结点

                P1->Linkinfo(p);//数据对象连接到结点

                list1.InsertFront(P1);//向前生成list1

                p=new StringObject(a[i]);

                P1=list2.CreatNode();

                P1->Linkinfo(p);

                list2.InsertRear(P1);//向后生成list2

        }

        list1.PrintList();

        cout<<"list1长度:"<<list1.Length()<<endl;

        list2.PrintList();

        cout<<"要求删除的字符串\"cat\""<<endl;

        p=new StringObject(sp);//为了程序的通用性只能多一次转换

        P1=list1.Find(*p);

        delete p;

        if(P1!=NULL){

                cout<<"删除cat:"<<endl;

                P1=list1.DeleteNode(P1);

                delete P1;

                list1.PrintList();

                cout<<"list1长度:"<<list1.Length()<<endl;

        }

        else cout<<"未找到"<<endl;

        cout<<"清空list1:"<<endl;

        list1.MakeEmpty();//清空list1

        list1.PrintList();

        for(i=0;i<5;i++){

                p=new StringObject(a[i]);

                P1=list3.CreatNode();

                P1->Linkinfo(p);

                list3.InsertOrder(P1);//升序创建list3

        }

        list3.PrintList();

        cout<<"程序结束:"<<endl;

        return 0;

}

矩形法(rectangle)积分近似计算公式为:

被积函数用派生类引入,被积函数定义为纯虚函数。

基类(integer)成员数据包括:积分上下限b和a;分区数n;步长step=(b-a)/n,积分值result。定义积分函数integerate()为虚函数,它只显示提示信息。

派生的矩形法类(rectangle)重定义integerate(),采用矩形法作积分运算。

派生的梯形法类(ladder)和辛普生法(simpson)类似。

请编程,用三种方法对下列被积函数

    1. sin(x),下限为0.0和上限为π/2;
    2. exp(x),下限为0.0和上限为1.0;
    3. 4.0/(1+x*x),下限为0.0和上限为1.0。

进行定积分计算,并比较积分精度。

解:使用类参数传递被积函数,因类有数据域,也可以同时传递积分上下限,可由读者进行修改。

#include<iostream>

#include<cmath>

using namespace std;

class Base{

protected:

    double result,a,b,step;//Intevalue积分值,a积分下限,b积分上限

    int n;

public:

        virtual double fun(double x)=0;//被积函数声明为纯虚函数

        virtual void Integerate(){

                cout<<"这里是积分函数"<<endl;

        }

        Base(double ra=0,double rb=0,int nn=2000){

                a=ra;

                b=rb;

                n=nn;

                result=0;

        }

        void Print(){

                cout.precision(15);

                cout<<"积分值="<<result<<endl;

        }

};

class Rectangle:public Base{

public:

        void Integerate(){

                int i;

                step=(b-a)/n;

                for(i=0;i<=n;i++) result+=fun(a+step*i);

                result*=step;

        }

        Rectangle(double ra,double rb,int nn):Base(ra,rb,nn){}

};

class Ladder:public Base{

public:

        void Integerate(){

                int i;

                step=(b-a)/n;

                result=fun(a)+fun(b);

                for(i=1;i<n;i++) result+=2*fun(a+step*i);

                result*=step/2;

        }

        Ladder(double ra,double rb,int nn):Base(ra,rb,nn){}

};

class Simpson:public Base{

public:

        void Integerate(){

                int i;

                step=(b-a)/n;

                result=fun(a)+fun(b);

                for(i=1;i<n;i+=2) result+=4*fun(a+step*i);

                for(i=2;i<n;i+=2) result+=2*fun(a+step*i);

                result*=step/3;

        }

        Simpson(double ra,double rb,int nn):Base(ra,rb,nn){}

};

class sinR:public Rectangle{//矩形法和梯形法采用并列结构

public:

        sinR(double ra,double rb,int nn):Rectangle(ra,rb,nn){}

        double fun(double x){return sin(x);}

};

class sinL:public Ladder{

public:

        sinL(double ra,double rb,int nn):Ladder(ra,rb,nn){}

        double fun(double x){return sin(x);}

};

class expR:public Rectangle{

public:

        expR(double ra,double rb,int nn):Rectangle(ra,rb,nn){}

        double fun(double x){return exp(x);}

};

class expL:public Ladder{

public:

        expL(double ra,double rb,int nn):Ladder(ra,rb,nn){}

        double fun(double x){return exp(x);}

};

class otherR:public Rectangle{

public:

        otherR(double ra,double rb,int nn):Rectangle(ra,rb,nn){}

        double fun(double x){return (4.0/(1+x*x));}

};

class otherL:public Ladder{

public:

        otherL(double ra,double rb,int nn):Ladder(ra,rb,nn){}

        double fun(double x){return (4.0/(1+x*x));}

};

class sinS:public Simpson{//辛普生法采用层次结构

public:

        sinS(double ra,double rb,int nn):Simpson(ra,rb,nn){}

        double fun(double x){return sin(x);}

};

class expS:public sinS{

public:

        expS(double ra,double rb,int nn):sinS(ra,rb,nn){}

        double fun(double x){return exp(x);}

};

class otherS:public expS{

public:

        otherS(double ra,double rb,int nn):expS(ra,rb,nn){}

        double fun(double x){return (4.0/(1+x*x));}

};

int main(){

        Base *bp;

        sinR sr(0.0,3.1415926535/2.0,100);

        bp=&sr;

        bp->Integerate();//动态,可以访问派生类定义的被积函数

        bp->Print();

        sinL sl(0.0,3.1415926535/2.0,100);

        bp=&sl;

        bp->Integerate();//动态,可以访问派生类定义的被积函数

        bp->Print();

        sinS ss(0.0,3.1415926535/2.0,100);

        bp=&ss;

        bp->Integerate();//动态,在层次中选

        bp->Print();

        expR er(0.0,1.0,100);

        bp=&er;

        bp->Integerate();//动态,可以访问派生类定义的被积函数

        bp->Print();

        expL el(0.0,1.0,100);

        bp=&el;

        bp->Integerate();//动态,可以访问派生类定义的被积函数

        bp->Print();

        expS es(0.0,1.0,100);

        bp=&es;

        bp->Integerate();//动态,在层次中选

        bp->Print();

        otherR or(0.0,1.0,100);

        bp=&or;

        bp->Integerate();//动态,可以访问派生类定义的被积函数

        bp->Print();

        otherL ol(0.0,1.0,100);//增加到100000也达不到辛普生法的精度

        bp=&ol;

        bp->Integerate();//动态,可以访问派生类定义的被积函数

        bp->Print();

        otherS os(0.0,1.0,100);

        bp=&os;

        bp->Integerate();//动态,在层次中选

        bp->Print();

        return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值