不一定是。参见介绍2017标准的《C++程序设计精要教程》,当所有基类以及基类的基类等等定义的纯虚函数,在派生类及其定义纯虚函数的基类之下的类中定义了相应(纯)虚函数的函数体,并且派生类没有自定义新的纯虚函数,则该派生类是具体类。
最简单的例子如下,派生类B不是具体类:
struct A{ //定义抽象基类
virtual void f()=0;
}A*p;
class B: public A{ //对于这种继承,A是父类,B是子类
void f(){ } //定义了基类的纯虚函数
virtual void g()=0; //类B定义了新的纯虚函数
};
viod main( ){
p->f(); //A::f()是可被main访问的,p-f()是正确的;
}
函数B::f()的访问权限private可以和A::f()的访问权限public不同,这种情况是允许的。编译程序进行的是静态的运行时的检查,此时p->f()并没有违背A::f()可访问性;若运行时p->f()最终调用B::f(),这已经无关编译程序了,编译程序并不负责运行时调用的函数的可访问性。
注意在C++中,常用基类和派生类描述类间的关系。当基类满足三个条件中的一个时,基类才可以被称为父类,而相应派生类才可以被称为子类。其它语言如java大多直接用父类或子类描述,因为java的定义天然满足父子类关系。
由上可知,基类被当作父类是有条件的。既然如此,当派生类有多个基类时,可能只有一部分基类可被称为父类,而相应的派生类被称为子类。多继承派生类能否成为具体类就更复杂了,需要声明的所有纯虚函数在其基类后都定义了函数体,并且当前多继承派生类没有说明新的纯虚函数。