【和春笋一起学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函数是基类中的函数,它不是虚函数,没有在派生类中重新定义,因此不需要使用作用域解析操作符。

相关推荐
会编程的土豆2 小时前
【数据结构与算法】动态规划
数据结构·c++·算法·leetcode·代理模式
6Hzlia4 小时前
【Hot 100 刷题计划】 LeetCode 78. 子集 | C++ 回溯算法题解
c++·算法·leetcode
所以遗憾是什么呢?4 小时前
【题解】Codeforces Round 1081 (Div. 2)
数据结构·c++·算法·acm·icpc·ccpc·xcpc
白藏y4 小时前
【C++】muduo接口补充
开发语言·c++·muduo
xiaoye-duck5 小时前
《算法题讲解指南:递归,搜索与回溯算法--综合练习》--14.找出所有子集的异或总和再求和,15.全排列Ⅱ,16.电话号码的字母组合,17.括号生成
c++·算法·深度优先·回溯
OOJO5 小时前
c++---vector介绍
c语言·开发语言·数据结构·c++·算法·vim·visual studio
Tanecious.6 小时前
蓝桥杯备赛:Day5-P1706 全排列问题
c++·蓝桥杯
胖咕噜的稞达鸭6 小时前
C++技术岗面试经验总结
开发语言·网络·c++·网络协议·tcp/ip·面试
Wild_Pointer.6 小时前
高效工具实战指南:从零开始编写CMakeLists
c++
kpl_207 小时前
智能指针(C++)
c++·c++11·智能指针