尽量以取代

包含的scanf和printf及其家族虽然是可移植的,高效的,但它们都还不够完美。尤其是它们不具型别安全(type-safe)性质,也都不可扩充。由于型别安全性和扩充性正是C++的基石,所以printf/scanf的弱点正是operator << 和 operator >> 的长处:

int i;

Rational r;  //r是一个分数(rational number)

.........

cin >> i >> r;

cout << i << r;

使用operator << 和 operator >>我们不需要像scanf/printf那样麻烦,编译器会根据不同的变量型别找出哪一个版本才是正确的,所以你不需要忧虑被处理的第一个对象型别为int,而第二个对象型别为Rational。哈哈,这是C++给我们的福利,再也不用像C语言中那样写复杂的输入输出了,让C++编译器去操这个心吧!!

无论是内建型别(如int)还是我们自定义的型别(如Rational),其读写的形式都是相同的。

当然还有一个问题是我们要自己通过运算符的重载来实现自定义型别的operator << 和 operator >>,下面是完善的一段代码,但是由于机器上的VC6.0对友元函数的支持有问题,所以不能编译成功。

不过把

#include
using namespace std;
替换成

#include
VC6.0中的下面程序正常了。


#include
using namespace std;

class Rational
{
public:
	Rational(int numerator = 0,int denominator = 1);//因为有默认的参数,这是一个默认构造函数

private:
	int n,d;
	friend istream& operator >> (istream& s,Rational& r);//加上friend表示这是一个友员函数,能够访问类的私有成员
	friend ostream& operator << (ostream& s,const Rational& r);
};

Rational::Rational(int numerator,int denominator)
{
	n = numerator;
	d = denominator;
}

istream& operator >> (istream& s,Rational& r)//这不是类的成员函数,不要加上类Rational这个作用域
{
	s >> r.n >> r.d;
	return s;
}

ostream& operator << (ostream& s,const Rational& r)
{
	s << r.n << '/' << r.d;
	return s;
}

int main(int argc,char *argv[])
{
	int i;	
	Rational r;  //r是一个分数(rational number)	
		
	cin >> i >> r;	
	cout << i << r;
	return 0;
}


某些情况下回头使用老东西还是可以理解的理由如下

1.某些iostream的实现效率比不上对应的C stream函数,而有可能你的程序会视此为一个重要差异。但需要记住的是效率问题对一般的iostream并不成立,只有特殊实现才会如此。

2.在标准化过程中,iostream程序曾在某些十分基本的地方做了修改,所以某些需要最大移植能力的应用程序可能会发现,不同的iostream版本支持不同的标准。

3.由于iostream程序库中的classes有constructors,而中的函数没有。

最后还需记住的是从技术上来说,已经没有所谓的.当标准委员会删除其它non-C标准头文件的扩展名时,就消灭了它。

如果你的编译器同时支持,(上面的程序在VC6.0中就是这样的)则这两个头文件有些轻微的不同。如果你#include,你取得的是隐藏域namespace std内的iostream程序库的元素,但如果你#include,你是在global scope中取得那些元素。在global scope中取得那些元素可能会造成名称冲突,而namespaces正是被设计用来阻止这类问题的发生。

除此之外,也比少了两个字,对许多人而言这个理由或许足够了呢。

你可能感兴趣的:(Effective,C++,读&思)