虚函数提供了一种更为灵活的多态性机制。虚函数允许函数调用与函数体之间的联系在运行时才建立,也就是在运行时才决定如何动作,即所谓的功能晚绑定。
5.4.1 虚函数的定义和使用
虚函数的定义是在基类中进行的,在成员函数原型的声明语句之前冠以关键字“virtual”,从而提供一种借口。一班虚函数成员的定义语法是:
virtual 函数类型 函数名(形参表)
{
函数体
}
当基类中的某个成员函数被声明为虚函数后,此虚函数就可以在一个或多个派生类中被重新定义。在重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型的顺序都必须与基类中的原型完全相同
虚函数的作用就是可以在派生类当中重新定义函数体,并且通过指向基类对象的指针和基类对象的引用来访问基类或者派生类中的同名函数。
虚函数的定义使用 virtual。
#include <iostream>
using namespace std;
class point
{
public:
point(double a = 0, double b = 0)
{
x = a, y = b;
}
virtual double area()
{
cout << "call point's area function"<<endl;
return 0.0;
}
protected:
double x, y;
};
class rectangle :public point
{
public:
rectangle(double a = 0, double b = 0, double c = 0, double d = 0) :point(a, b)
{
x1 = c, y1 = d;
}
double area()
{
cout << "call rectangle's area function" << endl;
return (x1 - x)*(y1 - y);
}
protected:
double x1, y1;
};
class circle :public point
{
public:
circle(double a, double b, double c) :point(a, b)
{
r = c;
}
double area()
{
cout << "call circle's area fundation"<<endl;
return 3.14*r*r;
}
protected:
double r;
};
double calcarea(point &ref)
{
return ref.area();
}
int main()
{
point p(0, 0);
rectangle r(0, 0, 1, 1);
circle c(0, 0, 1);
cout << calcarea(p) << endl;
cout << calcarea(r) << endl;
cout << calcarea(c) << endl;
system("pause");
return 0;
}
为什么把基类中的area声明成virtual就正确了呢?这是因为关键字virtual的作用是指示编辑器正确的选择ref.area函数。
//例5-3 有一个交通工具类vehicle,将它作为基类派生出汽车类motorvehicle,
//再将汽车类motorehicle作为基类派生出小汽车类car和卡车类trunk,
//声明这些类并定义一个虚函数用来显示各类信息.
#include <iostream>
using namespace std;
class vehicle
{
public:
/*virtual*/ void message()
{cout << "Vehicle Message " << endl;}
private:
int wheels;
float weight;
};
class motorVehicle :public vehicle
{
void message()
{cout << "MotorVehicle Message " << endl;}
private:
int messagers;
};
class car : public motorVehicle //声明MotorVehicle类的公用派生类Car
{
public:
void message()
{ cout << "Car Message " << endl; }
private:
float engine; //发动机的马力数
};
class truck : public motorVehicle //声明MotorVehicle类的公用派生类Truck
{
public:
void message()
{ cout << "Truck Message " << endl; }
private:
int loadpay; //载重量
};
int main()
{
vehicle v,*p = &v;;
motorVehicle m;
car c;
truck t;
p->message(); //调用基类成员函数
p = &m; // Vehicle类指针p指向MotorVehicle类对象
p->message(); //调用MotorVehicle类成员函数
p = &c; // Vehicle类指针p指向Car类对象
p->message(); //调用Car类成员函数
p = &t; // Vehicle类指针p指向Truck类对象
p->message(); //调用Truck类成员函数
system("pause");
return 0;
}