当前位置: 首页 > article >正文

C++学习笔记----9、发现继承的技巧(二)---- 重用目的的继承

        现在你对继承的基本语法已经比较熟悉了,是时候探索继承是c++语言中重要属性的一个主要原因了。继承是一个装备允许你平衡既有代码。本节会举出基于代码重用目的的继承的例子。

1、WeatherPrediction类

        假想你有一个任务,写一个程序来发出简单的天气预报,要用华氏度与摄氏度。作为程序员天气预报可能有一点儿超出你的领域,所以包含一个基于当前温度与当前金星与火星之间的距离写来用于天气预报的第三方的类库。第三方包用编译好的库进行分发,是为了保护预报算法的知识产权,但是你可以看到类定义。weather_prediction模块接口文件如下:

export module weather_prediction;

import std;

// Predicts the weather using proven new-age techniques given the current
// temperature and the distance from Jupiter to Mars. If these values are
// not provided, a guess is still given but it's only 99% accurate.
export class WeatherPrediction
{
public:
	// Virtual destructor
	virtual ~WeatherPrediction();

	// Sets the current temperature in Fahrenheit
	virtual void setCurrentTempFahrenheit(int temp);

	// Sets the current distance between Jupiter and Mars
	virtual void setPositionOfJupiter(int distanceFromMars);
	
	// Gets the prediction for tomorrow's temperature
	virtual int getTomorrowTempFahrenheit() const;
	
	// Gets the probability of rain tomorrow. 1 means
	// definite rain. 0 means no chance of rain.
	virtual double getChanceOfRain() const;
	
	// Displays the result to the user in this format:
	// Result: x.xx chance. Temp. xx
	virtual void showResult() const;
	
	// Returns a string representation of the temperature
	virtual std::string getTemperature() const;

private:
	int m_currentTempFahrenheit{ 0 };
	int m_distanceFromMars{ 0 };
};

        注意该类将所有的成员函数都标识为virtual,因为该类假定它们会在继承类中被重载。

        该类解决了程序的大部分问题。然而,通常情况下就是这样,这并没有准确地完成你的需求。首先,所有的温度都是以华氏度给的。你和应用程序需要以摄氏度运行。还有,showResult()成员函数可能不是你想要的结果显示的方式。

2、在继承类中添加功能

        在学习继承时,添加功能是描述的第一个技巧。本质上,你的程序需要的就是像WeatherPrediction类但是还要有一些额外的华丽的点缀。听起来像是一个重用代码的继承的好的案例。我们先开始定义一个新的类,MyWeatherPrediction,它继承自WeatherPrediction:

import weather_prediction;
export class MyWeatherPrediction : public WeatherPrediction
{
};

        前面的类定义编译没有问题,MyWeatherPrediction类可以用于WeatherPrediction的位置。它提供了同样的功能,但是还没有任何新意。第一次修改,你可能想添加类的摄氏度的知识。你可能有一点儿左右为难,因为你不知道类内部是怎么做的。如果所有的内部计算都用的是华氏的,你怎么加上摄氏度的支持呢?一个方法是使用继承类做为中间商,在用户之间交互,谁能用什么度,基类呢,只能理解华氏度。

        支持摄氏度的第一步就是添加成员函数允许客户设置以摄氏度而不是华氏度的当前温度,来得到明天的预报,以摄氏度而不是华氏度。你还需要私有的辅助函数来双向转换摄氏度与华氏度。这些函数可以是静态的,因为对于类实例是一样的。

export class MyWeatherPrediction : public WeatherPrediction
{
public:
	virtual void setCurrentTempCelsius(int temp);
	virtual int getTomorrowTempCelsius() const;
private:
	static int convertCelsiusToFahrenheit(int celsius);
	static int convertFahrenheitToCelsius(int fahrenheit);
};

        新的成员函数与父类的命名规则保持一致。记住从其它代码的角度,MyWeatherPrediction对象有所有的定义在MyWeatherPrediction与WeatherPrediction中的功能。适应父类的命名规范提供了一致的接口。

        华氏度与摄氏度的转换留给大家去做吧,实在做不来,上网上搜一下也能获取!另两个成员函数就比较有趣了。用摄氏度设置当着温度,需要首先转换温度,然后用它能理解的单位给到父类:

void MyWeatherPrediction::setCurrentTempCelsius(int temp)
{
	int fahrenheitTemp{ convertCelsiusToFahrenheit(temp) };
	setCurrentTempFahrenheit(fahrenheitTemp);
}

        可以看到,一旦温度被转换,就可以调用基类的既有的功能。同样的,getTomorrowTempCelsius()的实现使用父类既有的功能去获得华氏度温度,但是在返回之前转换一下结果:

int MyWeatherPrediction::getTomorrowTempCelsius() const
{
	int fahrenheitTemp{ getTomorrowTempFahrenheit() };
	return convertFahrenheitToCelsius(fahrenheitTemp);
}

        两个新的成员函数高效重用了父类,因为它们“打包”既有的功能,用一种提供了新的接口的方式来使用它。

        也可以添加新功能与父类既有的功能毫无关系。例如,可以添加一个成员函数来从互联网上访问另外的预报,或者一个成员函数基于预报的天气建议相关活动。

3、在继承类中替换功能

        继承的另外的主要技术是替换既有的功能。在WeatherPrediction类中的showResult()成员函数急需整容。MyWeatherPrediction可以重载成员函数来用它自己的实现替换它的行为。

新的MyWeatherPredition类定义如下:

export class MyWeatherPrediction : public WeatherPrediction
{
public:
	virtual void setCurrentTempCelsius(int temp);
	virtual int getTomorrowTempCelsius() const;
	void showResult() const override;

private:
	static int convertCelsiusToFahrenheit(int celsius);
	static int convertFahrenheitToCelsius(int fahrenheit);
};

        下面是一个新的,用户更友好的重载showResult()成员函数的实现:

void MyWeatherPrediction::showResult() const
{
	println("Tomorrow will be {} degrees Celsius ({} degrees Fahrenheit)",
		getTomorrowTempCelsius(), getTomorrowTempFahrenheit());

	println("Chance of rain is {}%", getChanceOfRain() * 100);

	if (getChanceOfRain() > 0.5) {
		println("Bring an umbrella!");
	}
}

        对于使用这个类的客户,就像旧版本的showResult()从来没有存在过。只要对象是MyWeatherPrediction,就会调用新的版本。作为这些改变的结果,MyWeatherPrediction作为一个带有新功能适应更确定的目的的新类出现。但是,它并不需要太多的代码,因为它利用了基类的既有的功能。


http://www.kler.cn/news/362493.html

相关文章:

  • 百度搜索推广和信息流推广的区别,分别适用于什么场景!
  • 【跨平台】ReactNative 入门初探
  • uniapp,获取头部高度
  • #深度学习:从基础到实践
  • 后台管理员登录实现--系统篇
  • VMware下安装Centos 7.6
  • 数据库产品中审计与日志(Auditing and Logging)的功能简介
  • kebuadm部署k8s集群
  • 智联云采 SRM2.0 testService SQL注入漏洞复现
  • 【软件测试: jmeter工具】OS进程取样器调用python
  • 【算法】KMP字符串匹配算法
  • redis未授权访问
  • QExcel 保存数据 (QtXlsxWriter库 编译)
  • JMeter 动态参数赋值实践
  • Docker 安装Postgres和PostGIS,并制作镜像
  • centos系统防火墙SELinux设置指令
  • TensorFlow:强大的机器学习框架
  • Vue3获取ref元素的几种方式
  • 海报在线制作系统小程序源码
  • vue 页面导出gif图片 img 导出gif 超简单~ 可修改播放速度
  • UI自动化测试
  • 运动监测网站毕设基于SpringBootSSM框架的计算机毕业设计
  • 【无人机设计与控制】差异化创意搜索DCS求解无人机路径规划MATLAB
  • 数据结构与算法——Java实现 45.根据后缀表达式建树
  • 在使用new Date()生成时间戳时,发现数据库中 的时间总是多出一秒钟。
  • Android SELinux——neverallow问题处理(十六)