在继承层次结构中,父类和子类可能会定义同样的成员函数(方法)来实现同一种操作,但是由于父类比子类更抽象,所以两者的具体实现会不一样,运行时多态性能确保调用的是想要的那个方法。
这在JAVA中是通过“重写”机制实现的:
父类和子类具有相同的方法,其返回值、参数类型、方法名都相同,但具体实现不同。当一个父类引用绑定子类的对象时,该方法的调用是调用所绑定的子类对象中所定义的具体实现。
在C++中,没有JAVA的这种“重写”机制,要实现相同的功能需要通过虚函数:
如果基类和派生类定义了相同的函数,但是具有不同的实现,这时,用基类指针指向派生类对象,在通过这个基类指针调用前述的成员函数时,我们希望能够通过基类指针调用派生类中的实现,但是实际上它调用的是基类的函数实现,如果想基类指针调用的是它指向的派生类的实现,就要在基类的该同名函数前加virtual关键字,这时此函数就是虚函数。
而且虚函数只对基类指针和基类引用有效,对基类对象无效,就是说如果把派生类对象赋值给基类对象那么该基类对象调用的还是基类中的函数。声明一个函数为虚函数时,会在类结构里加上一个指针,称为虚指针,它指向一个虚函数表。
只要某个类的成员函数前加了virtual关键字,那么派生类的同名函数(要求返回类型同、形参列表同、名字相同)也默认是虚函数,即使没有加virtual。
当然,如果只需要在子类对象调用父类中的某一方法时实现不同的操作,那么不需要用虚函数,直接在子类中重新定义该方法即可。这种情况称为编译时多态。
定义矩形类Rectangle,具有长、宽两个属性,double area();计算面积。然后定义一个立方体类Cuboid,继承了矩形类,还增加了高度这个属性,double area();返回的是立方体表面积。分别用C++和JAVA测试
(1)JAVA实现
public class Rectangle {
protected int width,length;
public Rectangle(int width,int length){
this.width=width;
this.length=length;
}
public double area(){//获取矩形面积
int s=width*length;
System.out.println("矩形面积为"+s);
return s;
}
}
public class Cuboid extends Rectangle{
private int height;
public Cuboid(int width, int length, int height) {
super(width, length);
// TODO Auto-generated constructor stub
this.height=height;
}
public double area(){
int s=2*(width*height+length*height+width*length);
System.out.println("立方体表面积为"+s);
return s;
}
}
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Rectangle r1=new Rectangle(3,2);
Rectangle c1=new Cuboid(3,2,5);
r1.area();
c1.area();
}
}
程序运行结果:
矩形面积为6
立方体表面积为62
(2)C++实现
#include<iostream>
using namespace std;
//基类,矩形类
class Rectangle{
protected:
int width,length;
public:
Rectangle(int width,int length){
this->width=width;
this->length=length;
}
virtual double area();//获取矩形面积,声明其为虚函数
};
double Rectangle::area(){
int s=width*length;
cout<<"矩形面积为"<<s<<'\n';
return s;
}
//派生自Rectangle的立方体类,和Rectangle有同样的area()成员函数
class Cuboid :public Rectangle{
protected:
int height;
public:
Cuboid(int width, int length, int height):Rectangle(width,length){
this->height=height;
}
double area();
};
double Cuboid::area(){
int s=2*(width*height+length*height+width*length);
cout<<"立方体表面积为"<<s<<'\n';
return s;
}
int main(){
Rectangle r1(3,2),c0=Cuboid(3,2,5),*c;
Cuboid c1(3,2,5);
c=new Cuboid(3,2,5);
Rectangle& cc=c1;
r1.area();//r1: Rectangle对象
c0.area();//c0: 用Cuboid对象初始化的Rectangle对象
c->area(); //c : 指向Cuboid的Rectangle指针
cc.area();//cc: 基类引用
delete c;
c=NULL;
}
程序运行结果:
矩形面积为6
矩形面积为6
立方体面积为62
立方体面积为62