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

相关推荐
selfsongs6 小时前
指针、内存管理、现代 C++ 特性
c++
吃着火锅x唱着歌7 小时前
Effective C++ 学习笔记 条款37 绝不重新定义继承而来的缺省参数值
c++·笔记·学习
2401_841495647 小时前
【数据结构】B+树
数据结构·数据库·c++·b+树·概念·结构·操作原理
小保CPP7 小时前
OCR C++ Tesseract按行识别字符
c++·人工智能·ocr·模式识别·光学字符识别
阿米亚波8 小时前
【C++】流式数据输入处理(不完全整理)
开发语言·c++·笔记
皓月斯语9 小时前
【C++基础】三目运算符
开发语言·数据结构·c++
初願致夕霞10 小时前
C++懒汉单例设计详解
服务器·开发语言·c++
脱胎换骨-军哥10 小时前
C++分布式系统设计:从通信引擎到分布式共识
开发语言·c++·分布式
脱胎换骨-军哥11 小时前
C++零成本抽象理论深度拆解:现代C++如何在不牺牲性能的前提下提供高级语法封装
java·开发语言·c++
_wyt00111 小时前
01背包问题详解
c++·背包dp