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.只是理论模型,要用于实际还得仔细修改。