11.1.1 为何用多态
下面程序,将Tuna 实例传递给Fish 参数,并通过该参数调用基类的Swim();
#include <iostream>
using namespace std;
class Fish
{
public :
void Swim()
{
cout << " Fish swims !" <<endl ;
}
};
class Tuna:public Fish
{
public :
void Swim ()
{
cout << " Tuna swims !"<<endl ;
}
};
void MakeFishSwim(Fish& InputFish)
{
InputFish.Swim();
}
int main ()
{
Tuna myDinner;
myDinner.Swim();
MakeFishSwim(myDinner);
return 0;
}
输出:
Tuna swims!
Fish swims!
Tuna 类以公有方式继承了Fish 类,它覆盖了方法Fish::swim(). 在main函数,直接调用Tuna::Swims() ,并将myDinner(Tuna类) 作为实参传递给了MaksFishSwim(),而该函数将其视为Fish 类引用,话句话说,虽然传入的是,Tuna 对象,MakeFishSwim(Fish& )也将其视为Fish ,进而调用Fish::Swim() . main ()函数输出,显示,虽然传入的是Tuna类对象,但得到的是Fish 的输出 。
然而调用 InputFish.Swim();时,用户希望执行的是Tuna::swim()。要实现这种多态行为-----让Fish 参数表现出其实际类型(派生类Tuna)的行为,可将Fish::swim()声明为虚函数。
11.1.2 使用虚函数实现多态
声明为虚函数如下:
class Base
{
virtual 函数类型 函数名()
{
}
};
程序:
#include <iostream>
using namespace std;
class Fish
{
public :
virtual void Swim()
{
cout << " Fish swims !" <<endl ;
}
};
class Tuna:public Fish
{
public :
void Swim ()
{
cout << " Tuna Swims "<<endl ;
}
};
class Carp:public Fish
{
public :
void Swim ()
{
cout << " Carp swims !"<<endl ;
}
};
void MakeFishSwim(Fish& InputFish)
{
InputFish.Swim();
}
int main ()
{
Tuna myDinner;
Carp myLunch ;
myDinner.Swim();
MakeFishSwim(myDinner);
MakeFishSwim(myLunch);
return 0;
}
输出:
Tuna swims!
Tuna swims!
Carp swims !
分析:
函数MakeFishSwim();与上一个例子一样,但输出却截然不同。首先根本没有调用Fish::swim().因为存在覆盖版本Tuna::swim( )和 Carp::swim () ,他们优先于被声明为的虚函数Fish::swim()。这很重要,它意味着,MakeFishSwim()中,可以通过Fish&参数调用派生类定义的Swim(), 而无需知道该参数指向的是哪种类型的对象。
这就是,多态,将派生类对象视为基类对象,并执行派生类的swim()实现。