osream和ofstream之:对象,继承和引用
ostream和ofstream类
ostream和ofstream类凸现了引用的一个有趣属性。ofstream对象可以使用ostream 类的方法, 这使得文件愉入/输出的格式与控制台输入/输出相同。使得能够将特性从一个类传递给另一个类的语言特性被称为继承,简单地说, ostream是基类(因为ofstrearn是建立在它的基础之上的而ofstream是派生类(因为它是从ostream派生而来的。派生类继承了基类的方法, 这意味抒ofstream对象可以使用基类的特性, 如格式化方法precision()和setf()。
继承的另一个特征是, 基类引用可以指向派生类对象,而无需进行强制类型转换。 这种特征的一个实际结果是,可以定义一个接受基类引用作为参数的函数,调用该函数时,可以将基类对象作为参数, 也可以将派生类对象作为参数。 例如, 参数类型为ostream&的函数可以接受ostrearn对象(如cout)或声明的ofstream对象作为参数.
程序通过调用同一个函数(只有函数调用参数不同)将数据写入文件和显示到屏幕上来说明了这一点 。 该程序要求用户输入望远镜物镜和一些目镜的焦距, 然后计算并显示每个目镜的放大倍数。 放 大倍数等千物镜的焦距除以目镜的焦距, 因此计算起来很简单。 该程序还使用了一些格式化方法, 这些方 法用千cout和ofstream对象(在这个例子中为fout)时作用相同。
#include <iostream> #include <fstream> #include <cstdlib> using namespace std; const int LIMIT = 5; void file_it(ostream& os, double fo, const double fe[], int n) { ios_base::fmtflags initial; initial = os.setf(ios_base::fixed); //save initial formatting state os.precision(0); os << "Focal length of object: " << fo << "mm "; os.setf(ios::showpoint); os.precision(1); os.width(12); os << "f.1.eyepiece"; os.width(15); os << "magnification" << endl; for (int i = 0; i < n; i++) { os.width(2); os << fe[i]; os.width(15); os << int(fo / fe[i] + 0.5) << endl; } os.setf(initial); //restore initial formatting state } int main() { ofstream fout; const char* fn = "ep-data.txt"; fout.open(fn); if (!fout.is_open()) { cout << "Can't open " << fn << ".Bye "; exit(EXIT_FAILURE); } double objective; cout << "Enter the focal length of your " "telescope object in mm: "; cin >> objective; double eps[LIMIT]; cout << "Enter the focal lengths, in mm, of " << LIMIT << " eyepieces: "; for (int i = 0; i < LIMIT; i++) { cout << "Eyepiece #" << i + i << ": "; cin >> eps[i]; } file_it(fout, objective, eps, LIMIT); file_it(cout, objective, eps, LIMIT); cout << "Done "; return 0; }
对于该程序, 最重要的一点是, 参数OS(其类型为ostream&)可以指向ostream对象(如cout), 也可以指向ofstream对象(如fout)。该程序还演示了如何使用ostream类中的格式化方法。
setf()
setf()可以设置各种格式化状态。
setf(ios_base::fixed)将对象置于使用定点表示法的模式;
setf(ios_base::showpoint)将对象置千显示小数点的模式 , 即使小数部分为零。
precision()
precision()指定显示多少位小数(假定对象处于定点模式下)。所有这些设置都将一直保持不变,直到再次调用相应的 方法重新设置它们。
width()
width()设置下一次输出操作使用的字段宽度,这种设置只在显示下一个值时有效, 然后将恢复到默认设置。默认的字段宽度为零, 这意味右刚好能容纳下要显示的内容。
ios_base::fmtflags initial; initial = os.setf(ios_base::fixed); //save initial formatting state os.setf(initial); //restore initial formatting state
函数file_it()使用了两个有趣的方法调用
setf()返回调用它之前有效的所有格式化设置。 ios_base::fintflags是存储这种信息所需的数据类型名称。 因此 , 将返回值赋给initial将存储调用file_it()之前的格式化设置, 然后便可以使用变点initial作为 参数来调用setf(), 将所有的格式化设置恢复到原来的值。因此, 该函数将对象回到传递给file_it()之前的状态。