纯虚函数
纯虚函数是一种特殊的虚函数,这是一种没有具体实现的虚函数。纯虚函数的定义格式为:
class <类名>
{
virtual <类型说明符> <函数名> ( <参数表> )=0;
};
其中,<函数名>是纯虚函数名。该函数的实现用赋值为0来表示,被定义为无。
在一个基类中说明一个纯虚函数,它不对应任何具体实现,该虚函数的实现在它的派生类中。
拿一个例子具体说明纯虚函数的作用:
<span style="font-size:18px;">#include <iostream>
using namespace std;
class Point//抽象类
{
public:
Point(int i=0,int j=0)
{ x0=i;y0=j; }
virtual void Draw()=0;//定义的基类的纯虚函数
private:
int x0,y0;
};
class Line:public Point
{
public:
Line(int i=0,int j=0,int m=0,int n=0):Point(i,j)//派生类Line的构造函数
{ x1=m;y1=n; }
void Draw()
{ cout<<"Line::Draw() called.\n"; }
private:
int x1,y1;
};
class Ellipse:public Point
{
public:
Ellipse(int i=0,int j=0,int p=0,int q=0):Point(i,j)//派生类Ellipse的构造函数
{ x2=p;x2=q; }
void Draw()
{ cout<<"Ellipse::Draw() called.\n"; }
private:
int x2,y2;
};
void Drawobj(Point *p)//定义的类外的函数
{
p->Draw();
}
int main()
{
Line *lineobj=new Line;
Ellipse *ellipseobj=new Ellipse;
Drawobj(lineobj);//函数的调用
Drawobj(ellipseobj);
return 0;
}</span>
输出的结果为:Line::Draw() called.
Ellipse::Draw() called.
程序分析:在函数Drawobj()中,调用了对象指针p所指向的Draw()函数,该形参进行动态联编,在运行时选择。
抽象类
定义:不能被定义对象的类,唯一的用途是被继承,这种类被称为抽象类。
抽象类是一种特殊的类,这种类不能定义对象,它的作用主要是用来组织一个继承的层次结构,并由它提供一个公共的根,而且相关的子类由它派生出来。抽象类用来描述一组子类的共同的操作接口,它用作基类,而完整的实现由子类完成。如果一个抽象类的派生类中没有定义虚函数,只是继承了基类的纯虚函数,则这个派生类还是一个抽象类。如果一个抽象类的派生类中给出了基类纯虚函数的实现,则这个派生类就是一个可以创建对象的具体类。可见,纯虚函数是抽象类的必要条件。
<span style="font-size:18px;">class B
{
public:
virtual void init()=0;
virtual void write(char *pstring)=0;
};
class D1:public B
{
public:
virtual void init()
{
...
}
};
class D2:public B
{
public:
virtual void init()
{
'''
}
virtual void write()
{
...
}
};
class D3:public D1
{
public:
virtual void write()
{
...
}
}</span>
分析:B类是抽象类,因为它有两个纯虚函数。
D1类也是抽象类,因为它继承了B类的一个纯虚函数write()。
D2类是具体类,因为实现了两个基类中的纯虚函数。
D3类是具体类,因为实现了纯虚函数。
纯析构函数
构造函数不能说明为虚函数,而析构函数可以说明为虚函数,其方法是在析构函数前边加上virtual说明符。
如果一个基类的析构函数被说明为虚析构函数,则它的派生类中析构函数也是虚析构函数,可以不在派生类的析构函数前加virtual说明符。
虚析构函数的作用相当于使用运算符delete删除一个对象时,能确保析构函数被正确的执行。因为设置虚析构函数可以采用动态联编,于是在运行时选择析构函数。
<span style="font-size:18px;">#include <iostream>
using namespace std;
class A
{
public:
virtual ~A()//虚析构函数
{ cout<<"A::~A() called.\n"; }
};
class B:public A
{
public:
B(int i)//构造函数
{ buffer=new char[i]; }
~B()//虚函数析构
{
delete [] buffer;
cout<<"B::~B() called.\n";
}
private:
char *buffer;
};
class fun(A *a)
{
delete a;
}
int main()
{
B *b=new B(10);
fun(b);
return 0;
}</span>
输出的结果为:B::~B() called.
A::~A() called.
若在基类的类体内没有说明虚析构函数,采用静态联编,输出:A::~A() called.