1.构造函数和析构函数中调用虚函数
(1)采用静态编译。
(2)在编译阶段自动联接自己类中的函数或基类中的函数,不在派生类中重定义一个函数。
注:构造函数和析构函数中调用的虚函数,派生类都不一定存在的情况下,只能去调用基类或者自身的函数。
example 1
#include <iostream.h>
class A
{
public:
A() {}
virtual void func() {cout<<"A construction."<<endl;}
~A() {}
virtual void fund() {cout<<"Destruction A."<<endl;}
};
class B:public A
{
public:
B() {func();}
void fun() {func();}
~B() {fund();}
};
class C:public B
{
public:
C() {}
void func() {cout<<"C construction."<<endl;}
~C() {fund();}
void fund() {cout<<"C destruction."<<endl;}
};
int main()
{
C c;
c.func();
}
程序输出:
A construction.
C construction.
C destruction.
Destruction A.
2.空虚函数
纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
(1)表示:
virtual void 函数名() {} //空虚函数
virtual void 函数名()=0; //纯空虚函数
(2)目的:保证类在继承路线上接口唯一。
含义:若派生类想存取虚函数时,必须建立一条从基类到派生类的虚函数路径,许多中间类也必须描述该虚函数以保证其后的派生类可以使用虚函数。
注:类中含有纯虚函数该类就叫做抽象类,不能定义对象。
(3)空虚函数:无函数体,但具有函数形式,空虚函数是可以被调用的。
(4)纯虚函数:
A.没有函数实现过程的虚函数。
B.纯虚函数不可被调用,将纯虚函数的实现留给派生类以实现动态联编完成继承中的多态。
example 2
#include <iostream.h>
class Point
{
int x, y;
public:
Point(int i = 0, int j = 0) {x = i; y = j;}
virtual void set()=0;
virtual void draw()=0;
};
class Line:public Point
{
int x1, y1;
public:
Line(int i = 0, int j = 0, int m = 0, int n = 0):Point(i, j)
{x1 = m; y1 = n;}
void set() {cout<<"Line::set() called."<<endl;}
void draw() {cout<<"Line::draw() called."<<endl;}
};
class Elipes:public Point
{
int x2, y2;
public:
Elipes(int i = 0, int j = 0, int p = 0, int q = 0):Point(i, j)
{x2 = p; y2 = q;}
void set() {cout<<"Elipes::set() called."<<endl;}
void draw() {cout<<"Elipes::draw() called."<<endl;}
};
void drawobj(Point *p)
{p->draw();}
void setobj(Point *p)
{p->set();}
int main()
{
Line *lineobj = new Line;
Elipes *elipesobj = new Elipes;
drawobj(lineobj);
drawobj(elipesobj);
setobj(lineobj);
setobj(elipesobj);
}
程序输出:
Line::draw() called.
Elipes::draw() called.
Line::set() called.
Elipes::set() called.
注:基类Point不是虚基类,系统将会为派生类Line和Elipes分别建立基类副本,在派生类Line、Elipes的构造函数中,都要完整表示对基类构造函数的调用以及参数描述。代码中存在的问题,缺两个delete来释放内存。
3.在基类中定义纯虚函数,不实现其函数功能。
意义:
(1)将基类中set和draw函数的实现放在不同的派生类中去独立实现。
(2)由于纯虚函数是虚函数,只要使基类指针指向派生类对象就可以实现动态联编,就可以调用不同派生类中独立实现的每一个set和draw函数。
4.抽象类
(1)抽象类是一个特殊的类,即含有纯虚函数。
(2)位于继承中的上层——为派生类提供一个统一的界面。
作用:将相关派生类组织在一个继承层次结构中,为子类提供一个公共的根——保证相关子类从同一个根派生而来。
注意:
(1)抽象类只做基类。
(2)不能够创建抽象类的对象。
(3)抽象类的构造函数声明为受保护权限。
(4)不可将抽象类作为函数参数以及函数返回值类型。
(5)可以设置指向抽象类对象的指针,但该指针只可用于指向派生类对象,引用也是如此。
(6)将抽象类中的纯虚函数交给派生类来实现,派生类中也可以不实现,交给派生类的下一级派生类来实现,但是在派生类中必须定义自己的纯虚函数版本。