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

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

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

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

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

示例源码:

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

#include 
#include 
#include 
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);
}

执行结果:

C/C++ 对象、继承和引用_第1张图片

写入到的文件:

C/C++ 对象、继承和引用_第2张图片

下述代码行将目镜数据写入到文件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 的设置将被修改,然后被恢复。

你可能感兴趣的:(C/C++学习,c++,开发语言,c语言)