隐藏基类函数
有时派生类需要根据自身特点改写从基类继承的函数,比如动物都有叫声,在描述动物的类中可以定义speak()函数,不同的动物,叫声也不同,比如猫、狗都有特定叫声。若定义猫科类,该类继承自动物类,继承了speak()函数,但在猫科类中需要改写speak()函数,用于描述猫特有的叫声。
派生类中重新定义基类同名函数的方法,称为对基类函数的覆盖或改写,覆盖后基类同名函数在派生类中被隐藏。定义派生类对象调用该函数时,调用的是自身的函数,基类同名函数不被调用。
接下来通过一个案例说明派生类隐藏基类函数的方法,如例1所示。
例1
1 #include <iostream>
2 using namespace std;
3
4 class Animal //定义基类
5 {
6 public:
7 //定义speak()函数
8 void speak() { cout << "animal language!" << endl; }
9 };
10 class Cat :public Animal //定义派生类
11 {
12 public:
13 //定义speak()函数
14 void speak() { cout << "cat language: miaomiao!" << endl; }
15 };
16
17 int main()
18 {
19 Cat cat; //定义派生类对象
20 cat.speak(); //通过派生类调用speak()函数
21 cat.Animal::speak(); //调用基类同名函数
22 system("pause");
23 return 0;
24 }
程序运行结果如图1所示。
图1 例1运行结果
例1中,在基类和派生类中定义了同名函数speak(),此时派生类中的函数会覆盖基类同名函数。从运行结果看,代码第20行派生类对象调用的是它自己的speak()函数,若想调用基类同名函数,方法如代码第21行所示,应该在函数名前加上基类名和作用域运算符“::”。
若基类中有多个重载函数并且派生类中有同名函数,则基类中的所有同名函数被隐藏,若想调用基类函数仍然要显式使用基类名。除此之外,在定义了派生类后,可以定义一个基类的指针,通过派生类的构造函数创建对象。修改例1,在main()函数中定义基类指针变量并让它指向派生类对象,观察通过基类指针调用speak()函数会显示什么结果,如例2所示。
例2
1 #include <iostream>
2 using namespace std;
3
4 class Bird //定义鸟类
5 {
6 public:
7 //定义鸟在天空飞的成员函数
8 void fly_in_sky() { cout << "bird fly in sky!" << endl; }
9 //定义鸟呼吸的成员函数
10 void breath() { cout << "bird breath!" << endl; }
11 };
12 class Fish //定义鱼类
13 {
14 public:
15 //定义鱼在水里游的成员函数
16 void swim_in_water() { cout << "fish swim in water!" << endl; }
17 //定义鱼呼吸的成员函数
18 void breath() { cout << "fish breath!" << endl; }
19 };
20 class WaterBird:public Bird, public Fish //定义水鸟类
21 {
22 public:
23 //定义水鸟行为的成员函数
24 void fly_swim() { cout << "waterbird cant fly and swim!" << endl; }
25 };
26 int main()
27 {
28 WaterBird waterbird; //定义水鸟对象
29 waterbird.fly_in_sky(); //调用从鸟类继承来的flyinsky()函数
30 waterbird.swim_in_water(); //调用从鱼类继承来的swiminwater()函数
31 system("pause");
32 return 0;
33 }
程序运行结果如图2所示。
图2 通过多重继承定义派生类
例2中定义了三个类Bird、Fish、WaterBird。WaterBird多重继承自Bird和Fish,因此WaterBird自然继承了鸟类和鱼类的所有成员,并能够访问其中的公有和受保护成员,在主函数中定义派生类对象并调用基类成员函数fly_in_sky()和swim_in_water(),程序运行正确。