C++ 多态性应用实验

本文展示了C++中使用模板类实现顺序存储容器MyVector、链式存储容器MyList以及栈和队列的代码。文章讨论了泛型思想、继承和派生的应用,并提供了测试用例验证设计的功能和效率。在实践中遇到了友元函数重载和模板类继承时的使用问题,并给出了相应的解决方案。
摘要由CSDN通过智能技术生成

实验目的

1. 理解面向对象思想中泛型的概念、重要意义;

2. 正确声明和使用模板类;

实验内容

  1. 仿照std::vector, 以模板类的形式实现一个通用的顺序存储容器 MyVector
  2. 仿照std:: list, 以模板类的形式实现一个通用的链式存储容器MyList。
  3. 以模板类的形式实现栈和队列。

基本要求:

1)体现泛型思想、体现继承和派生;

2要给出关于设计思想的描述或是对设计过程做出必要说明和解释。

3)编写相应的测试用例来验证或者测试所设计类的基本功能及效率。

实验过程

MyVictor.h:

//
// Created by HASEE on 2022/6/6.
//

#ifndef UNTITLED_MYVECTOR_H
#define UNTITLED_MYVECTOR_H

#include <iostream>

using namespace std;
template<typename T>
class MyVector {
        template<typename U>
    friend ostream& operator<< (ostream &out, const MyVector<U> &obj);
private:
    int len=0;
    T *space= nullptr;
public:
    int getlen(){
        return len;
    }
    explicit MyVector(int size=0);
    ~MyVector();//析构
    MyVector(const MyVector& myv1); //拷贝构造
    MyVector(MyVector &&myv) noexcept ;  //移动构造
    //重载[] =
    T& operator[](int index);
    MyVector& operator=(const MyVector& mv2);
};

#endif //UNTITLED_MYVECTOR_H

MyVictor.cpp:

//
// Created by HASEE on 2022/6/6.
//

#include "MyVector.h"
#include <iostream>
using namespace std;
template<typename T>
MyVector<T>::MyVector(int size) {
   len=size;
   space=new T[len];
}

template<typename T>
MyVector<T>::~MyVector() { //析构函数
   if(space != nullptr){
       delete[] space;
       space= nullptr;
       len=0;
   }
}

template<typename T>
MyVector<T>::MyVector(const MyVector &myv1) { //拷贝构造函数
    len=myv1.len;
    space=new T[len];
    for(int i=0;i<len;++i){
        space[i]=myv1.space[i];  //复制内容
    }
}
//[]重载
template<typename T>
T &MyVector<T>::operator[](int index) {
    return space[index];
}
//移动构造
template<typename T>
MyVector<T>::MyVector(MyVector &&myv) noexcept {
    if(myv.space == nullptr)
        return;
    space=myv.space;
    myv.space= nullptr;
}

template<typename T>
MyVector<T> & MyVector<T>::operator=(const MyVector<T> &mv2) {
    if(space!= nullptr){
        delete[] space;
        space= nullptr;
        len=0;
    }
    len=mv2.len;
    space=new T[len];
    for (int i = 0; i < len; ++i) {
        space[i]=mv2.space[i];
    }
    return  *this;
}
//<<重载
template<typename T>
ostream & operator << (ostream &out, const MyVector<T> &s) {
    for(int i=0;i<s.len;++i){
        out<<s.space[i];
    }
   out<<endl;
    return out;
}
int main(){
        MyVector<int> mv1(10);
        for (int i = 0; i < mv1.getlen(); i++){
            mv1[i] = i + 1;//调用重载函数[]
            cout << mv1[i]<<"  ";
        }
        cout << endl;
        MyVector<int> mv2 = mv1;//调用拷贝构造函数
        for (int i = 0; i < mv2.getlen(); ++i){
            cout<<mv2[i]<<"  ";
        }
        cout << mv2 <<endl; //调用重载<<
//        system("pause");
}		

结果:

LinarList.h(线性表基类):

//
// Created by HASEE on 2022/6/7.
//

#ifndef UNTITLED_LINARLIST_H
#define UNTITLED_LINARLIST_H

template <typename T>
class LinearList{
public:
    LinearList(){}
    virtual ~LinearList(){}
    //纯虚函数
    virtual int Length()const = 0;//求表的长度
//    virtual int Search(T& x)const = 0;
//    virtual int Locate(int i)const = 0;//在表中定位第i个元素位置,返回表项序号
    virtual T getData(int i)const = 0; //取第i个的值
//    virtual void setData(int i, T& x) = 0;//修改第 i个的值
    virtual bool Insert(int i, T& x) = 0;
    virtual T Remove(int i) = 0;
    virtual bool IsEmpty()const = 0;//判空


};
#endif //UNTITLED_LINARLIST_H

 MyList.h (单链表):

//
// Created by HASEE on 2022/6/6.
//

#ifndef UNTITLED_MYLIST_H
#define UNTITLED_MYLIST_H
#include "LinarList.h"
template <typename T>
struct Node{
    T data;//数据域
    Node<T>* link;//指针域,指向下一个节点
    Node() //仅初始化指针的构造函数
    {
        Node<T> *ptr = NULL;
        link = ptr;
    }
    Node(const T& item, Node<T> *ptr = NULL) //初始化数据和指针成员的构造函数
    {
        data = item;
        link = ptr;
    }
};

template <typename T>
class MyList : public LinearList<T>{
protected:
    Node<T>* first; //头节点,使第i个结点对应下标第i个元素
public:
    MyList(){
        first=new Node<T>;}
    MyList(const T& x){//指定头节点
        first=new Node<T>(x);
    }
    MyList(MyList<T>& l);
    ~MyList(){
        makeEmpty();
    }
    void makeEmpty(){
        Node<T>* q;
        while (first->link != NULL)//找到各个结点并删除
        {
            q = first->link;              //保存被删结点
            first->link = q->link;     //从链上摘下该结点,通过头指针的link的移动来实现
            delete q;            //删除
        }
    }
    Node<T>* getHead()const{
        return first;}
    void setHead(Node<T>* p){
        first=p;
    }
    int Length()const;
//    int Search(T& x)const;
    Node<T>* Locate(int i)const;
    T getData(int i)const;
//    void setData(int i, T& x);
    bool insert(T& x);//尾插入
    bool Insert(int i, T& x);
    T Remove(int i);
//    void headAdd();
//    void tailAdd();
    bool IsEmpty()const{
        return first->link == NULL;
    }
//    void input();
//    void output();
    MyList<T>& operator=(const MyList<T>& L);

};

#endif //UNTITLED_MYLIST_H

Mylist.cpp(基于单链表类实现栈和队列):

//
// Created by HASEE on 2022/6/6.
//
#include <iostream>
#include "MyList.h"
#include <cstdio>
template<typename T>
MyList<T>::MyList(MyList<T> &l) {
    T value;
    Node<T>* fptr=l.getHead();//声明一个结点遍历参数链表
    Node<T>* nptr=first=new Node<T>;//新链表的头结点
    while (fptr->link != NULL){//逐个复制参数链表的结点
        value=fptr->link->data;
        nptr->link=new Node<T>(value);
        nptr=nptr->link;
        fptr=fptr->link;
    }
}

//O(n)
template<typename T>
int MyList<T>::Length() const {
    Node<T>* p=first->link; //指向一号节点
    int count=0;
    while (p!= NULL){
        p=p->link;
        count++;
    }
    return count;
}
//O(n)
template<typename T>
Node<T> *MyList<T>::Locate(int i) const {//定位第i个元素的位置
    if (i < 0) return NULL;       // i不合理
    Node<T>* current = first;
    int k = 0;
    while (current != NULL && k < i)
    {
        current = current->link;
        k++;
    }
    return current;        //返回第 i 号结点地址或NULL
}
template<typename T>
T MyList<T>::getData(int i) const {
    if(i<1)
    return NULL;
    Node<T>* current= Locate(i);
    return current->data;
}

//template<typename T>
//void MyList<T>::setData(int i, T &x) {//修改第i个元素的值
//    if(i<1)
//        return;
//    Node<T>* current= Locate(i);
//    if(current== nullptr)
//        return;
//    current->data=x;
//}
//O(n)
template<typename T>
bool MyList<T>::Insert(int i, T &x) {
    Node<T>* current= Locate(i);
    if(current== NULL)//无插入位置
        return false;
    Node<T>* newNode=new Node<T>(x);
//    创建新节点
    if(newNode== NULL)
        return false;
    newNode->link=current->link;
    current->link=newNode;
    return true;
}
//O(n)
template<typename T>
T MyList<T>::Remove(int i) {//删除第i个元素,x带回删除值
    T x;
    Node<T>* current= Locate(i-1);
    if(current== NULL||current->link== NULL)
        return false;//删除不成功
    Node<T>* del=current->link;
    current->link=del->link;
    x=del->data;
    delete del;
    return x;
}

template<typename T>
MyList<T> &MyList<T>::operator=(const MyList<T> &L) {
    T value;
    Node<T>* srcptr=L.getHead();
    Node<T>* tptr=first;
    makeEmpty();//清空后复制
    while (srcptr->link!= nullptr){
         value=srcptr->link->data;
         tptr->link=new Node<T>(value);
         tptr=tptr->link;
         srcptr= srcptr->link;
    }
    tptr->link= nullptr;
    return *this;
}

template<typename T>
bool MyList<T>::insert(T& x) {
    if(this->IsEmpty()){
        Node<T>* newNode=new Node<T>(x);
        first->link=newNode;
        return true;
    }
    Insert(Length(),x);
    return true;
}


//栈
template<typename T>
class LinkedStack: public MyList<T>{
public:
    void push(T x){
        Node<T>* tmp=new Node<T>;
        tmp->data=x;
        this->insert(x);
    }
    T pop(){//返回出栈值
        int len=this->Length();
        T x=this->Remove(len);
        return x;
    }
};

//队列
template<typename T>
class LinkedQueue:public MyList<T>{
public:
    void EnQueue(T x){
        Node<T>* tmp=new Node<T>;
        tmp->data=x;
        this->insert(x);
    }
    T DeQueue(){//返回出队值
        T x= this->Remove(1);
        return x;
    };
};

//测试
int main(){
    LinkedStack<int> stack;
    int a=11;
    stack.insert(a);
    stack.push(1);
    stack.push(2);
    stack.push(3);
    int i=stack.pop();
    int m=stack.getData(2);
    std::cout<<m<<std::endl;
    std::cout<<i<<std::endl;
    LinkedQueue<int> queue;
//    int b=22;
//    queue.insert(b);
    queue.EnQueue(12);
    queue.EnQueue(11);
    queue.EnQueue(20);
    int out=queue.DeQueue();
    std::cout<<out<<std::endl;
}

结果:

 

实验总结

        在对<<进行重载时,常常不能编译,虽然写了重载但是貌似编译器找不到然后就一直报这个错误,网上也找了很多资料不知道是什么原因,后面突然找到了一个解决办法,在友元函数前再新建一个模板,然后就可以编译了,但是仍然不清楚这是什么原因。

        在使用继承时,如果构造类为模板类的话,派生类不能直接使用继承到的数据和方法,直接写的话会出现找不到标识的错,想要解决这个问题需要通过this指针使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值