一种接口,多种方法
基类声明所有派生类的公共接口,而让派生类定义具体的方法来实现这些接口,这就是”一种接口,多种方法“的思想,而虚函数的应用就是这种思想的体现。
示例:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;
class figure {
protected:
double x, y;
public:
void set_dim(double i, double j)
{
x = i;
y = j;
}
virtual void show_area()
{
cout << "No area computation defined "; //该类中不定义具体的面积计算方法,
cout << "for this class.\\n"; //这里仅是给个提示
}
};
class triangle : public figure {
public:
void show_area()
{
cout << "Triangle with height ";
cout << x << " and base " << y;
cout << " has an area of ";
cout << x * 0.5 * y << ".\\n";
}
};
class rectangle : public figure {
public:
void show_area()
{
cout << "Rectangle with dimensions ";
cout << x << " x " << y;
cout << " has an area of ";
cout << x * y << endl;
}
};
int main()
{
figure *p; //声明基类型指针
triangle t; //派生类对象
rectangle r;
p = &t;
p->set_dim(10.0, 5.0);
p->show_area();
p = &r;
p->set_dim(10.0, 5.0);
p->show_area();
return 0;
}
运行输出:$ ./onemul
Triangle with height 10 and base 5 has an area of 25.
Rectangle with dimensions 10 x 5 has an area of 50 上面程序中,三角形面积计算类 triangle 和 矩形面积计算类 triangle 使用了同样的接口函数 show_area() ,但它们分别提供了各自的计算面积的方法。在这两种面积的计算方法中,都会使用到 2 个参数:三角形是底和高,矩形是长和宽。但是我们是否可以派生出一个计算圆面积的类呢?而在计算圆面积时,只会用到一个参数就是半径,那么要给 set_dim() 传递 1 个还是 2 个参数呢,答案是 1 个和 2 个都可以。先看使用 2 个参数的情况下:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;
class figure {
protected:
double x, y;
public:
void set_dim(double i, double j)
{
x = i;
y = j;
}
virtual void show_area()
{
cout << "No area computation defined "; //该类中不定义具体的面积计算方法,
cout << "for this class.\\n"; //这里仅是给个提示
}
};
class triangle : public figure {
public:
void show_area()
{
cout << "Triangle with height ";
cout << x << " and base " << y;
cout << " has an area of ";
cout << x * 0.5 * y << ".\\n";
}
};
class rectangle : public figure {
public:
void show_area()
{
cout << "Rectangle with dimensions ";
cout << x << " x " << y;
cout << " has an area of ";
cout << x * y << endl;
}
};
class circle : public figure {
public:
void show_area()
{
cout << "Circle with radius ";
cout << x;
cout << " has an area of ";
cout << 3.14 * x * x << endl;
}
};
int main()
{
figure *p; //声明基类型指针
triangle t; //派生类对象
rectangle r;
circle c;
p = &t;
p->set_dim(10.0, 5.0);
p->show_area();
p = &r;
p->set_dim(10.0, 5.0);
p->show_area();
p = &c;
p->set_dim(9.0, 10);
p->show_area();
return 0;
}
运行输出:$ ./onemul2
Triangle with height 10 and base 5 has an area of 25.
Rectangle with dimensions 10 x 5 has an area of 50
Circle with radius 9 has an area of 254.34 输出结果是正确的。但是在计算圆面积前使用的 set_dim() 函数里的第 2 个参数是没必要的,在这里它是一个哑值,你给它 10 也好,8 也罢,只要是一个数值,就能保证 set_dim() 函数与基类中的原型匹配。但这种方式看起来相当令人不快,它让我们必须记住这种调用形式(我们实际上只希望,在计算圆面积时,只要传递一个半径参数便够了),这也违背了 ”一种接口,多种方法“ 的思想。一个更好的解决办法是给 set_dim() 中的参数 y 赋一个默认值,比如在基类中将 set_dim(double i, double j) 改成 set_dim(double i, double j=0) 即可。这样一来,在 main() 中计算圆面积时再调用到该该函数时,只需要 set_dim(9.0); 这么写便行。
小型示例程序并不能体现虚函数的全部功能,通常在大型的系统中,多态才会显示出最大的威力。 |