当子类继承父类时,父类的成员函数可以分为三类:接口(纯虚函数)、接口和实现(实现了的虚函数)、普通成员函数。
class Base
{
public:
virtual void draw() =0; //纯虚函数
virtual void error() //虚函数
{
cout<<"error"<<endl;
}
int objectID() //普通成员函数
{
cout<<"objectID"<<endl;
return 0;
}
};
对于接口:当一个类中有一个函数是纯虚函数时,这个类就是一个抽象类,不能有实体对象;它的子类必须实现这个接口,否则该子类也是一个抽象类,不能有实体对象。 还有一个很特殊的情况,就是在父类中实现了接口的定义,但是它还是一个纯虚函数,父类依然是个抽象类,一般不会使用这种情况:
class Base
{
public:
virtual void draw() =0 //纯虚函数
{
cout<<"draw()"<<endl;
}
virtual void error() //虚函数
{
cout<<"error"<<endl;
}
int objectID() //普通成员函数
{
cout<<"objectID"<<endl;
return 0;
}
};
对于接口和实现:即父类实现了该接口的缺省实现,就是在子类没有重新定义这个接口时,则使用这个缺省定义的接口。所以子类有了选择权,提高了代码的复用,并支持了面向对象(多态)。
对于普通成员函数:父类不允许子类改变该函数的实现,当子类也定义了相同类型的函数时,就会覆盖父类的对应类型的函数。
对于所有成员函数都声明为non-virtual和所有函数都声明为virtual的错误分析:
当明确知道该类没有子类的时候,可以将所有的成员函数都声明为non-virtual,否则,这回使得子类没有空间进行特化工作(失去了多态的特性,也就减弱了面向对象)。
当所有的成员函数都声明为virtual类型时,又会造成效率的降低,因为只有在运行状态时编译器才能确定使用的是哪个成员函数,而且必须由有类中的虚函数指着去遍历查询虚函数类表才能找到对应的函数,效率就会下降。