【和春笋一起学C++】(六十一)公有继承中的多态

公有继承中的多态是指同一种方法在派生类和基类中具有不同的行为,具体的说,是指方法的行为取决于调用该方法的对象。多态,即具有多种形态,就是指同一个方法的行为随上下文而异。要实现多态公有继承,需要用到两种机制。

  1. 在派生类中重新定义基类的方法。
  2. 使用虚函数。

将《派生类和基类之间的关系》文章中的基类和派生类增加一个函数,用于计算各科成绩的平均分,基类对象有三科成绩,而派生类对象有五科成绩,这种情况下,同一方法在基类和派生类中的定义不同,可以用虚函数来实现基类和派生类中求各科成绩的平均分。基类和派生类的声明如下:

cpp 复制代码
class Student
{
public:
	...
    unsigned short get_yuwen_score() { return yuwen_score; }
	unsigned short get_shuxue_score() { return shuxue_score; }
	unsigned short get_yingyu_score() { return yingyu_score; }
	string get_name() { return name; }
	virtual unsigned short GetMean();
    virtual void show_score()
	{
		cout << "语文分数:" << yuwen_score << endl;
		cout << "数学分数:" << shuxue_score << endl;
		cout << "英语分数:" << yingyu_score << endl;
	}
    virtual ~Student() {}
private:
	std::string name;
	unsigned short yuwen_score;
	unsigned short shuxue_score;
	unsigned short yingyu_score;
};

class CulturalStudent :public Student
{
private:
	unsigned short lishi_score;
	unsigned short zhengzhi_score;
public:
	...
    virtual void show_score()
	{
		cout << "姓名:" << get_name() << endl;
		Student::show_score();
		cout << "历史分数:" << lishi_score << endl;
		cout << "政治分数:" << zhengzhi_score << endl;
	}
	virtual unsigned short GetMean();
};

说明:基类中声明GetMean函数时使用了关键字virtual,此时,GetMean,show_score函数被称为虚函数。

将会在派生类中重新定义的基类中的函数声明为虚函数,在基类中被声明为虚函数后,它在派生类中将自动成为虚函数。不过,一般在派生类的声明中使用关键字virtual来指出哪些函数是虚函数。

虚函数的定义如下:

cpp 复制代码
unsigned short Student::GetMean()
{
	return (yuwen_score + shuxue_score + yingyu_score) / 3;
}

unsigned short CulturalStudent::GetMean()
{
	return (get_shuxue_score() + get_yingyu_score() + get_yuwen_score() + zhengzhi_score + lishi_score) / 5;
}

说明:虚函数的实现不需要加关键字virtual,virtual关键字只用于类声明中的函数原型。

在程序中调用虚函数:

cpp 复制代码
int main()
{
	using namespace std;
	CulturalStudent st1("xiaoming", 82, 99, 84, 90, 91);
	Student st5("xiaohong", 90, 89, 78);
	cout << st1.GetMean() << endl;///调用派生类中的GetMean函数
	cout << st5.GetMean() << endl;///调用基类中的GetMean函数

	Student *st2 = &st1;
	Student *st3 = &st5;
	st2->get_shuxue_score();///调用基类中的get_shuxue_score方法
	st3->get_shuxue_score();///调用基类中的get_shuxue_score方法

	cout<<st2->GetMean()<<endl;///调用派生类中的GetMean方法
	cout<<st3->GetMean()<<endl;///调用基类中的GetMean方法
    return 0;
}

程序说明:

  1. 基类和派生类中都声明了GetMean函数,此时,程序将根据对象类型来确定使用哪个版本

如果要在派生类中重新定义基类的方法,则应将基类方法声明为虚拟的。这样,程序将根据对象类型而不是引用或指针的类型来选择方法版本。

  1. 如果方法是通过引用或指针调用的,如果函数没有使用virtual,程序将根据引用或指针类型确定调用的方法;如果函数使用了virtual,表明该函数在基类和派生类中都有定义,则程序将根据引用或指针指向的对象的类型来确定调用的方法。

3. 基类中声明了一个虚析构函数。在基类中定义虚函数后,通常将析构函数也设置成虚函数,以确保释放派生类对象时按正确的顺序调用析构函数。

  1. 派生类中的show_score函数展示了在派生类函数中调用基类函数的方式。
cpp 复制代码
    virtual void show_score()
	{
		cout << "姓名:" << get_name() << endl;
		Student::show_score();
		cout << "历史分数:" << lishi_score << endl;
		cout << "政治分数:" << zhengzhi_score << endl;
	}

派生类中的show_score函数显示新增的两个科目成绩,并调用基类中的show_score函数显示基类数据成员中的语数外三科成绩。在派生类方法中,必须使用作用域解析操作符来调用基类的虚函数, 该示例中如果没有使用作用域解析操作符,show_score函数将调用自身形成递归,导致无限循环**。**

示例中,get_name函数是基类中的函数,它不是虚函数,没有在派生类中重新定义,因此不需要使用作用域解析操作符。

相关推荐
AC赳赳老秦17 分钟前
用 OpenClaw 制定技术学习计划:根据目标岗位自动生成学习路线、推荐学习资源
开发语言·c++·人工智能·python·mysql·php·openclaw
ShineWinsu1 小时前
对于Linux:内核是如何组织管理IPC资源的解析
linux·服务器·c++·面试·笔试·线程·ipc
少司府1 小时前
C++进阶:红黑树
开发语言·数据结构·c++·b树·二叉树·红黑树
汉克老师1 小时前
GESP6级C++考试语法知识(五十五、动态规划----背包问题(八、混合背包)
c++·动态规划·dp·背包问题·gesp六级·混合背包问题
特种加菲猫1 小时前
哈希表的实现
开发语言·c++
玖釉-1 小时前
nvpro_core2 详解:NVIDIA Vulkan / OpenGL 图形样例背后的现代 C++ 基础库
c++·windows·图形渲染
不会C语言的男孩1 小时前
C++ Primer 第19章:特殊工具与技术
数据结构·c++
不会C语言的男孩2 小时前
C++ Primer 第18章:用于大型程序的工具
开发语言·c++
星恒随风2 小时前
C++ 类和对象入门(三):拷贝构造、赋值运算符重载和深浅拷贝
开发语言·c++·笔记·学习
Cx330❀2 小时前
【MySQL基础】库与表的全面操纵指南
linux·服务器·网络·数据库·c++·mysql