首先来看一下静态联编的例子:
#include <iostream>
using namespace std;
const double PI = 3.1415926;
class Point{
public:
Point(int x = 0, int y = 0){
this->x = x;
this->y = y;
}
double area(){
return 0.0;
}
private:
int x, y;
};
class Circle : public Point{
public:
Circle(int x, int y, int R) : Point(x, y), r(R){}
double area() {
return PI * r * r;
}
private:
int r;
};
int main(){
Point A(10, 10);
cout << "A area = " << A.area() << endl;
Circle B(10, 10, 20);
cout << "B area = " << B.area() << endl;
Point *p;
p = &B;
cout << p->area() << endl;
Point &pp = B;
cout << pp.area() << endl;
return 0;
}
运行结果:
A area = 0
B area = 1256.64
0
0
分析:
后面两个结果是0,很明显是调用了基类的area函数,而不是调用派生类中的area函数,这跟我们的本意不一致。解决办法是把基类中的area函数声明为虚函数,这时当某个虚函数通过指针或引用调用时,编译器产生的代码直到运行是才能确定应该调用哪个版本的函数(动态联编),这就是实现了所谓的多态。被调用的函数是与绑定到指针或者引用上的对象的动态类型相匹配的那一个。下面的例子中调用的是Point类型的area函数,这样就获得了我们想要的结果(注意虚函数的声明方式):
#include <iostream>
using namespace std;
const double PI = 3.1415926;
class Point{
public:
Point(int x = 0, int y = 0){
this->x = x;
this->y = y;
}
//虚函数
virtual double area(){
return 0.0;
}
private:
int x, y;
};
class Circle : public Point{
public:
Circle(int x, int y, int R) : Point(x, y), r(R){}
//显示声明覆盖掉基类的area函数
double area() override{
return PI * r * r;
}
private:
int r;
};
int main(){
Point A(10, 10);
cout << "A area = " << A.area() << endl;
Circle B(10, 10, 20);
cout << "B area = " << B.area() << endl;
Point *p;
p = &B;
cout << p->area() << endl;
Point &pp = B;
cout << pp.area() << endl;
return 0;
}
运行结果:
A area = 0
B area = 1256.64
1256.64
1256.64