任务描述
本关任务:设计人类、英语学生类和复读机类三个类。
相关知识
为了完成完成本关任务,你需要掌握虚函数的基本使用。
多态性
在面向对象的方法中,多态性是指向不同对象发送同一个消息,不同对象在接收时会产生不同的行为(方法)。
通俗点说就是可以不用像 C 语言中为了求多种图形的面积而针对不同的图形各设计一个独立名字的函数,在 C++ 中只要设计一个专门用于求面积的函数名即可。这个专门用于求面积的函数名可以作为各种求图形面积的函数名。
这么做的好处在于程序设计者可以省去设立多个函数名对应多个函数的麻烦,使用的时候统一用同一个函数名就可调用具有不同功能的函数。
多态在 C++ 中的实现可以是函数的重载、运算符的重载和虚函数,本实训我们介绍虚函数的使用。
虚函数
我们知道在同一个类中是不能定义两个名字相同、参数个数和类型完全相同的函数,否则就是重复定义。但是在类的继承层次结构中,在不同的层次中可以出现名字相同、参数个数和类型相同而功能不同的函数。这时系统会根据同名覆盖的原则决定调用的对象。
那么有没有一种方法,用同一种调用形式,既能调用派生类又能调用基类的同名函数?即不通过不同的对象名去调用不同派生层次中的同名函数,而是通过指针调用它们,虚函数就是用来解决这个问题的。
虚函数是一种动态的重载方式。虚函数的作用是允许在派生类中重新定义与基类同名的函数,并可以通过基类指针或引用来访问基类和派生类中同名函数。
C++ 中要声明一个成员函数为虚函数,只需要在函数的声明前加上一个关键字 virtual 即可,然后就像对待普通成员函数那样,给它加上定义。
例如:
class Base
{
public:
virtual void VFunc(); // 声明一个虚函数
};
void Base::VFunc()
{
cout << "虚函数" << endl;
}
重写父类虚函数
当一个类继承了一个含有虚函数的类,子类就可以选择是否要对父类的虚函数进行重写。所谓重写,就是覆盖父类中的定义,提供一个自己的定义。当然也可以选择不重写,那么就沿用父类的定义。
要重写一个虚函数,需要增加一条与要重写的函数相同(参数与返回值)的函数声明,然后在声明后面加上说明符 override。
例如:
/* Base类的声明同上 */
class D1 : public Base // 继承 Base 类
{
public:
void VFunc() override; // 重写 VFunc 函数
};
void D1::VFunc()
{
cout << "覆盖父类实现" <<endl;
}
int main()
{
D1 b;
b.VFunc();
}
输出结果为:覆盖父类实现
在子类中重写虚函数时是可以重新定义访问性的,即使父类中虚函数的访问性为 private,在子类中仍然可以重写为 public。如果子类想要访问被重写的父类的定义,同样使用作用域运算符(::
)即可。
例如:
/* Base类的声明同上 */
class D1 : public Base // 继承 Base 类
{
public:
void VFunc() override; // 重写 VFunc 函数
};
void D1::VFunc()
{
Base::VFunc(); // 调用父类的定义
cout << "覆盖父类实现" <<endl;
}
int main()
{
D1 b;
b.VFunc();
}
输出结果为:
虚函数
覆盖父类实现
编程要求
在右侧编辑器中的Begin-End
之间补充代码,设计人类、英语学生类和复读机类三个类,具体要求如下:
-
人类( Chinese )
- 它有一个虚函数 greet,函数输出中文问候,即
你好
。
- 它有一个虚函数 greet,函数输出中文问候,即
-
英语学生类( EnglishLearner )
- 继承 Chinese 类,重写 greet 函数,访问性为 public,输出英文问候,即
Hello
。
- 继承 Chinese 类,重写 greet 函数,访问性为 public,输出英文问候,即
-
复读机类( Repeater )
- 继承 Chinese 类,以 public 访问性重写 greet 函数,函数调用 Chinese 类的 greet 函数。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试。
#include <iostream>
using namespace std;
/********* Begin *********/
class Chinese
{
//人类的声明
public:
virtual void greet();
};
//人类的定义
void Chinese::greet(){
cout<<"你好"<<endl;
}
class EnglishLearner : public Chinese
{
//英语学生类的声明
public:
void greet() override;
};
//英语学生类的定义
void EnglishLearner::greet(){
cout<<"Hello"<<endl;
}
class Repeater : public Chinese
{
//复读机类的声明
public:
void greet() override;
};
//复读机类的定义
void Repeater::greet(){
Chinese::greet();
}
/********* End *********/