LinearList.h抽象基类:
#ifndef LINEARLIST #define LINEARLIST //线性表的抽象基类 template<class T> class LinearList { public: LinearList(){};//如果派生类不需要向基类构造函数传递参数,则就会调用基类默认构造函数,所以,要么不写,要么就自己写默认构造函数。 ~LinearList(){};//派生类也会调用基类的析构函数。 virtual int Size()const=0; virtual int Length()const=0; virtual int Search(T& x)const=0; virtual int Locate(int i)const=0; virtual bool getData(int i,T& x)const=0; virtual void setData(int i,T& x)=0; virtual bool Insert(int i,T& x)=0; virtual bool Remove(int i,T& x)=0; virtual bool IsEmpty()const=0; virtual bool IsFull()const=0; virtual void Sort()=0; virtual void input()=0; virtual void output()=0; //virtual LinearList<T>& operator=(LinearList<T>& L)=0; //在继承类中形参不同,故不能声明纯虚函数,否则继承类无法定义对象。 }; #endif
实现及测试文件:
///////////////////////// #include"LinearList.h" #include <iostream> #include <cstdlib> using namespace std; const int defaultSize=100; template<class T> class SeqList:public LinearList<T> { protected: T* data; int maxSize; int last; void reSize(int newSize); public: SeqList(int sz=defaultSize):data(new T[sz]),maxSize(sz),last(-1){} SeqList(const SeqList<T>& L); ~SeqList(){delete []data;} int Size()const{return maxSize;} int Length()const{return last+1;} int Search(T& x)const; int Locate(int i)const; bool getData(int i,T& x)const{if(i>0&&i<=last+1){x=data[i-1];return true;}else return false;} void setData(int i,T& x){if(i>0&&i<=last+1)data[i-1]=x;else {cerr<<"err"<<endl;exit(1);}} bool Insert(int i,T& x); bool Remove(int i,T& x); bool IsEmpty()const{return (last==-1)?true:false;} bool IsFull()const{return (last==maxSize-1)?true:false;} void Sort(){};//未提供具体的实现。 void input(); void output(); SeqList<T>& operator=(SeqList<T>& L); }; template<class T> SeqList<T>::SeqList(const SeqList<T>& L) { maxSize=L.maxSize; last=L.last; data=new T[maxSize]; if(data==NULL){ cerr<<"err"<<endl; exit(1); } T value; for(int i=0;i<=last;++i){ L.getData(i+1,value);setData(i,value); } } template<class T> SeqList<T>& SeqList<T>::operator=(SeqList<T>& L) { maxSize=L.maxSize; last=L.last; data=new T[maxSize]; if(data==NULL){ cerr<<"err"<<endl; exit(1); } T value; for(int i=0;i<=last;++i){ L.getData(i+1,value);setData(i,value); } return *this; } template<class T> void SeqList<T>::reSize(int newSize) { if(newSize<=0){ cerr<<"err"<<endl; exit(1); } if(newSize!=maxSize){ maxSize=newSize; T* ptr=new T[maxSize]; if(ptr==NULL){ cerr<<"err"<<endl; exit(1); } T* srcptr=data; T* destptr=ptr; n=last+1; while(n--) *destptr++=*srcptr++; delete []data; data=destptr; } } template<class T> int SeqList<T>::Search(T& x)const { for(int i=0;i<=last;++i) if(data[i]==x) return i+1; return 0; } template<class T> int SeqList<T>::Locate(int i)const { if(i>=1&&i<=last+1) return i; else return 0; } template<class T> bool SeqList<T>::Insert(int i,T& x) { if(i<0||i>last+1) return false; if(IsFull()) return false; for(int j=last;j>=i;--j) data[j+1]=data[j]; data[i]=x; ++last; return true; } template<class T> bool SeqList<T>::Remove(int i,T& x) { if(i<=0||i>last+1) return false; if(IsEmpty()) return false; x=data[i-1]; for(int j=i;j<=last;++j) data[j-1]=data[j]; --last; return true; } template<class T> void SeqList<T>::input() { cout<<"PLZ input element number-1:"<<endl; while(1){ cin>>last; if(last<=maxSize-1) break; cout<<"err! repeat."<<endl; } for(int i=0;i<=last;++i) cin>>data[i]; } template<class T> void SeqList<T>::output() { for(int i=0;i<=last;++i) cout<<"#"<<i+1<<":"<<data[i]<<" "; cout<<endl; } int main(int argc, char* argv[]) { SeqList<int> s(10); int val=2; s.input(); s.output(); cout<<"size: "<<s.Size()<<endl; cout<<"Length: "<<s.Length()<<endl; cout<<"Search: "<<s.Search(val)<<endl; cout<<"Locate: "<<s.Locate(2)<<endl; int val1,val2=99; s.getData(2,val1); cout<<"getData: "<<val1<<endl; s.setData(2,val2); s.getData(2,val1); cout<<"setData: "<<val1<<endl; s.Insert(0,val2);//插入是失败的,因为最初顺序表示满的。 s.output(); s.Remove(2,val1); s.output(); cout<<"IsEmpty(): "<<s.IsEmpty()<<endl; cout<<"IsFull: "<<s.IsFull()<<endl; system("pause"); return 0; }
运行结果:
PLZ input element number-1:
9
0 1 2 3 4 5 6 7 8 9
#1:0 #2:1 #3:2 #4:3 #5:4 #6:5 #7:6 #8:7 #9:8 #10:9
size: 10
Length: 10
Search: 3
Locate: 2
getData: 1
setData: 99
#1:0 #2:99 #3:2 #4:3 #5:4 #6:5 #7:6 #8:7 #9:8 #10:9
#1:0 #2:2 #3:3 #4:4 #5:5 #6:6 #7:7 #8:8 #9:9
IsEmpty(): 0
IsFull: 0
请按任意键继续. . .
要点分析:
1.抽象基类中没有数据成员,只有成员函数的接口,且都是纯虚函数。所以继承类中要实现全部的接口功能,把抽象基类覆盖掉,而且接口要完全相同。
2.抽象基类可以不提供构造和析构函数,这样在派生类中调用系统默认生成的抽象基类构造函数和析构函数。或者你自己定义抽象基类默认的构造函数
和析构函数,也可定义带参数的构造和析构函数,让派生类调用。派生类是必须要调用基类的构造函数和析构函数的,或者显示调用或者隐式调用。
构造函数先调用基类的在调用派生类的,析构函数先调用派生类的在调用基类的。
3.好处是为了利用多态机制。方便使用。
4.只是理论模型,要用于实际还得仔细修改。
时间: 2024-11-01 11:13:56