C/C++ 对象、继承和引用

发布时间:2023年12月31日

????????ostream和ofstream类凸现了引用的一个有趣属性。正如ofstream 对象可以使用 ostream类的方法,这使得文件输入/输出的格式与控制台输入/输出相同。使得能够将特性从一个类传递给另一个类的语言特性被称为继承。

????????简单地说,ostream 是基类,而ofstream 是派生类。派生类继承了基类的方法,这意味着ofstream对象可以使用基类的特性,如格式化方法precision()和setf()。

????????继承的另一个特征是,基类引用可以指向派生类对象,而无需进行强制类型转换。这种特征的一个实际结果是,可以定义一个接受基类引用作为参数的函数,调用该函数时,可以将基类对象作为参数,也可以将派生类对象作为参数。例如,参数类型为 ostream &的函数可以接受 ostream 对象或声明的ofstream对象作为参数。

????????如下列程序,通过调用同一个函数(只有函调用参数不同)将数据写入文件和显示到屏幕上来说明了这一点。该程序要求用户输入望远镜物镜和一些目镜的焦距,然后计算并显示每个目镜的放大倍数。放大倍数等于物镜的焦距除以目镜的焦距,因此计算起来很简单。该程序还使用了一些格式化方法,这些方法用于cout和ofstream 对象(在这个例子中为fout)时作用相同。

示例源码:

// Len_file.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

void file_it(ostream& os, double fo, const double fe[], int n);
const int LIMIT = 5;

int main()
{
	ofstream fout;
	const char * fn = "ep-data.txt";
	fout.open(fn);
	if (!fout.is_open())
	{
		cout << "Can't open " << fn << ". Bye.\n";
		exit(EXIT_FAILURE);
	}
	double objective;
	cout << "Enter the focal length of your"
		"telescope objective in mm: ";
	cin >> objective;
	double eps[LIMIT];

	cout << "Enter the focal lengths, in mm, of " << LIMIT
		<< " EVEPIECES;\n";

	for (int i = 0; i < LIMIT; i++)
	{
		cout << "Eyepiece #" << i + 1 << ": ";
		cin >> eps[i];
	}

	file_it(fout, objective, eps, LIMIT);
	file_it(cout, objective, eps, LIMIT);
	cout << "Done\n";
	return 0;
}

void file_it(ostream& os, double fo, const double fe[], int n)
{
	ios_base::fmtflags initial;
	initial = os.setf(ios_base::fixed);
	os.precision(0);
	os << "Focal length of objective: " << fo << " mm\n";
	os.setf(ios::showpoint);	// 保存初始化格式的状态
	os.precision(1);
	os.widen(12);
	os << "f.1. eyepiece";
	os.width(15);
	os << "magnification" << endl;
	for (int i = 0; i < n; i++)
	{
		os.width(12);
		os << fe[i];
		os.width(15);
		os << int(fo / fe[i] + 0.5) << endl;
	}
	os.setf(initial);
}

执行结果:

写入到的文件:

下述代码行将目镜数据写入到文件ep-data.txt中:
?? ?
?? ?file_it(fout,objective, eps,LIMIT);
?? ?
而下述代码行将同样的信息以同样的格式显示到屏幕上:
?? ?
?? ?file it(cout,objective, eps,LIMIT);
?? ?
????????程序说明:
????????对于该程序,最重要的一点是,参数 os(其类型为 ostream &)可以指向 ostream 对象(如 cout),也可以指向ofstream对象(如fout)。该程序还演示了如何使用ostream类中的格式化方法。

????????方法 setf( )能够设置各种格式化状态。
例如,
????????方法调用 setf(ios_base::fixed)将对象置于使用定点表示法的模式;
????????setf(ios_base:showpoint)将对象置于显示小数点的模式,即使小数部分为零。
????????方法precision()指定显示多少位小数(假定对象处于定点模式下)。
????????所有这些设置都将一直保持不变,直到再次调用相应的方法重新设置它们。
????????方法width()设置下一次输出操作使用的字段宽度,这种设置只在显示下一个值时有效,然后将恢复到默认设置。默认的字段宽度为零,这意味着刚好能容纳下要显示的内容。
函数 file_it()使用了两个有趣的方法调用:

?? ?ios_base::fmtflags initial;
?? ?initial = os.setf(ios_base::fixed); ?? ?// 保存初始化格式状态
?? ?...
?? ?os.setf(initial);?? ?// 重复存储初始化状态
?? ?
????????方法setf()返回调用它之前有效的所有格式化设置is basefmtlags 是存储这种信息所需的数据类型名称。因此,将返回值赋给 initial 将存储调用 fle it()之前的格式化设置,然后便可以使用变量 initial 作为参数来调用 setf(),将所有的格式化设置恢复到原来的值。因此,该函数将对象回到传递给 ie it()之前的状态。
????????了解更多有关类的知识将有助于更好地理解这些方法的工作原理,以及为何在代码中使用 ios_base。
????????需要说明的最后一点是,每个对象都存储了自己的格式化设置。因此,当程序将 cout 传递给 file_it()时cout 的设置将被修改,然后被恢复;当程序将 fout 传递给 file_it()时,fout 的设置将被修改,然后被恢复。

文章来源:https://blog.csdn.net/wendyWJGU/article/details/135309707
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。