C++ Primer Plus书之--C++引用与类对象, 引用,集成,对象 2

引用与类对象

先看个引用与类对象的demo:

#include <iostream>
#include <string>
using namespace std;

string version1(const string & s1, const string & s2);
const string & version2(string & s1, const string & s2);
const string & version3(string & s1, const string & s2);

int main()
{
	string input;
	string copy;
	string result;
	
	cout << "Enter a string : " << endl;
	getline(cin, input);
	copy = input;
	cout << "input : " << input << endl;
	result = version1(input, "***");
	cout << "result : " << result << endl;
	cout << "Your original string input : " << input << endl;
	
	result = version2(input, "###");
	cout << "result : " << result << endl;
	cout << "Your original string input : " << input << endl;
	
	cout << "Reset original string " << endl;
	input = copy;
	// 这里会出问题, 因为version3中返回的是一个局部变量temp的引用
	// 而temp在version3执行完毕后就会不存在, 因此result去获取引用的时候就会挂掉
	result = version3(input, "@@@");
	cout << "result : " << result << endl;
	cout << "Your original string input : " << input << endl;
	return 0;
}

string version1(const string & s1, const string & s2)
{
	string temp;
	temp = s2 + s1 + s2;
	// 返回的是temp的副本, 按值返回
	return temp;
}

const string & version2(string & s1, const string & s2)
{
	s1 = s2 + s1 + s2;
	// 返回的是s1的引用, 安全的
	return s1;
}

const string & version3(string & s1, const string & s2)
{
	string temp;
	temp = s2 + s1 + s2;
	// 返回的是temp的引用, 但是这个是不安全的, 因为
	// temp是局部变量, 当version3执行完毕后temp就不存在了
	return temp;
}

程序运行结果:

需要注意的地方都在注释中写明了,  只需要额外注意一点就是version3这个函数, 由于返回的是局部变量temp的引用, 而temp在version3执行完毕的时候会被回收, 所以version3可能会造成程序崩溃.

引用与对象, 继承

看一个demo

// 对象, 继承, 引用
#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 not open " << fn << " bye " << endl;
		exit(EXIT_FAILURE);
	}
	
	double objective;
	cout << "Enter the focal length of your telescope objective in mm :";
	cin >> objective;
	double eps[LIMIT];
	cout << "Enter the local lengths , in mm of " << LIMIT << " eyepieces:" << endl;
	for(int i = 0; i < LIMIT; i++)
	{
		cout << "Eyepiece #" << i + 1 << endl;
		cin >> eps[i];
	}
	
	file_it(fout, objective, eps, LIMIT);
	file_it(cout, objective, eps, LIMIT);
	cout << "Done" << endl;
	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 " << endl;
	// 将对象置于显示小数点的模式
	os.setf(ios::showpoint);
	os.precision(1);
	// 设置下一次输出操作使用的字段宽度
	// 这种设置只在显示下一个值时有效, 然后将恢复到默认设置
	// 默认的字段宽度为零, 这意味着刚好能容纳下要显示的内容.
	os.width(12);
	os << "f.1.eyepieces";
	os.width(22);
	os << "magnification" << endl;
	for(int i = 0; i < n; i++)
	{
		os.width(12);
		os << fe[i];
		os.width(22);
		// 强制转换为int值
		os << int (fo / fe[i] + 0.5) << endl;
	}
	// 返回调用它之前有效的所有格式化设置.
	os.setf(initial);
}

程序运行结果为:

对应的输出到文件中的截图:

函数void file_it(ostream & os, double fo, const double fe[], int n);接收的是ostream 的引用对象, 而ofstream是ostream的子类, 因此函数也能接收fout和cout.

demo中关于现阶段没用到的几个方法都做了注释, 

方法setf()可以让我们更能够设置各种格式化状态. 例如: 方法调用setf(ios_base::fixed)将对象置于使用定点表示法的模式; setf(ios_base::showpoint)将对象置于显示小数点的模式, 即使小数部分为零. 方法precision()指定显示多少位小数(假定对象处于定点模式下). 所有这些设置都将一直保持不变, 直到再次调用相应的方法重新设置它们.

这个例子只要看懂为什么ostream & 能接收fout和cout就可, 关于格式化的问题可以慢慢理解

怎么使用引用

何时使用引用参数:

1.程序需要修改调用函数中的数据对象

2.通过传递引用而不是整个数据对象, 可以提高程序的运行速度.

引用, 指针, 值传递的使用规则:

对于使用传递的值, 而不做修改的函数:

1.如果数据对象很小, 如内置数据类型或小型结构, 则按值传递

2.如果数据对象是数组, 则使用指针, 因为这是唯一的选择, 并将指针声明为指向const的指针

3.如果数据对象是较大的结构, 则使用const指针, 或const引用, 以提高程序的效率, 这样可以节省复制结构所需的时间和空间.

4.如果数据对象是类对象,则使用const引用. 传递类对象参数的标准方式是按引用传递.

如果修改调用函数中数据的函数:

1.如果数据对象是内置数据类型, 则使用指针.

2.如果数据对象是数组, 则只能使用指针

3.如果数据对象是结构, 则使用引用或指针

4.如果数据对象是类对象, 则使用引用.

猜你喜欢

转载自blog.csdn.net/c1392851600/article/details/84717800