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;

}

《深入浅出 C++》视频教程详细、系统地介绍了 C++ 开发中方方面面的技术细节,整个课程涵盖知识点非常多,知识模块囊括 名字空间、类对象、继承多态、各类友元、异常机制、函数模板、类模板、STL容器操作等等,学完之后将拥有C++开发的非常坚实的功底。 注意:本套视频教程来源于线下的实体班级,因此视频中有少量场景对话学生问答,对此比较介意的亲们谨慎购买。 本套视频教程不仅会讲清楚概念相应知识点,而且会抽丝剥茧,讲清楚来龙去脉,站在编程语言设计者的角度讲清楚为什么会出现这样的语法,站得高才能看得远,而不仅仅纠缠于细碎的语法。既有登高望远的视角,又有俯身前行的实践,有别于市面上大多数流于表面的教程。下面是讲解迭代器的一节视频的截图: 每个知识点不仅仅会通过视频讲解清楚,并且会配以精心安排的实验作业,用来保证学习过程中切实掌握核心技术概念,通过实验来巩固,通过实验来检验,实验作业的目的是发现问题,发现技术盲点,通过答疑沟通夯实技术技能。注意:本套视频教程包含全套11套作业题,覆盖所有视频知识点,循序渐进,各个击破。下面是部分作业题目展示,每道题都有知识点说明,是检验学习效果的一大利器:常见问题:问:零基础可以学习吗?答:这门课程并非针对完全零基础的学员,学习这门课程需要对C语言有了一定了解的。问:遇到问题可以答疑吗?答:可以的,购买课程后可以联系到我,安排进入专门的QQ答疑群。不仅可以向老师提问,也可以跟其他同学讨论,结交兴趣相投的朋友。问:学完能做什么?答:C++是众多开发岗位的必备技能,也是进入面向对象编程领域的一门利器,可以胜任很多岗位的职业要求。尤其是对游戏开发、游戏引擎、算法、界面开发、系统开发等等,C++都是热门技术。
### 关于C++继承多态编程练习题及示例代码 #### 示例代码一:基于形状绘制的多态应用 以下是一个经典的多态应用场景,展示了如何通过基类指针调用派生类的方法。 ```cpp #include <iostream> using namespace std; // 基类 Shape 定义纯虚函数 draw() class Shape { public: virtual void draw() const = 0; // 纯虚函数 virtual ~Shape() {} // 虚析构函数 }; // 圆形类 Circle 继承自 Shape 并重写 draw 方法 class Circle : public Shape { public: void draw() const override { cout << "Drawing a Circle" << endl; } }; // 长方形类 Rectangle 继承自 Shape 并重写 draw 方法 class Rectangle : public Shape { public: void draw() const override { cout << "Drawing a Rectangle" << endl; } }; int main() { // 使用多态特性 Shape* shape1 = new Circle(); Shape* shape2 = new Rectangle(); shape1->draw(); // 输出 Drawing a Circle shape2->draw(); // 输出 Drawing a Rectangle delete shape1; delete shape2; return 0; } ``` 此代码利用了运行时多态[^2],即通过基类指针调用了派生类的具体方法。 --- #### 示例代码二:虚拟继承的应用场景 下面的例子演示了虚拟继承的作用以及构造函数初始化列表的行为。 ```cpp #include <iostream> using namespace std; class Base { public: Base() { cout << "Base Constructor Called\n"; } virtual ~Base() {} }; class Derived1 : virtual public Base { public: Derived1() { cout << "Derived1 Constructor Called\n"; } }; class Derived2 : virtual public Base { public: Derived2() { cout << "Derived2 Constructor Called\n"; } }; class FinalDerived : public Derived1, public Derived2 { public: FinalDerived() { cout << "FinalDerived Constructor Called\n"; } }; int main() { FinalDerived obj; return 0; } ``` 在此例子中,`Base` 类仅被实例化了一次,这是因为 `Derived1` `Derived2` 都采用了虚拟继承的方式[^3]。这有助于避免菱形继承中的重复成员问题。 --- #### 示例代码三:日期比较器的设计 这是一个稍微复杂的多态应用案例,涉及运算符重载继承的概念。 ```cpp #include <iostream> #include <string> using namespace std; class Date { protected: int year, month, day, hour, minute, second; public: Date(int y, int m, int d, int h, int min, int sec) : year(y), month(m), day(d), hour(h), minute(min), second(sec) {} bool operator<(const Date& other) const { if (year != other.year) return year < other.year; if (month != other.month) return month < other.month; if (day != other.day) return day < other.day; if (hour != other.hour) return hour < other.hour; if (minute != other.minute) return minute < other.minute; return second < other.second; } friend ostream& operator<<(ostream& os, const Date& date); }; ostream& operator<<(ostream& os, const Date& date) { os << date.year << "-" << date.month << "-" << date.day << " " << date.hour << ":" << date.minute << ":" << date.second; return os; } class DateTimeComparator { public: virtual bool compare(const Date& lhs, const Date& rhs) const = 0; virtual ~DateTimeComparator() {} }; class LessThanComparator : public DateTimeComparator { public: bool compare(const Date& lhs, const Date& rhs) const override { return lhs < rhs; } }; int main() { Date dt1(2000, 7, 4, 16, 45, 50); Date dt2(2000, 8, 4, 22, 15, 40); LessThanComparator comparator; cout << "dt1 < dt2: " << (comparator.compare(dt1, dt2) ? "true" : "false") << endl; return 0; } ``` 这段代码实现了日期时间的比较功能,并通过多态机制支持不同的比较逻辑[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值