我们经常在程序中看见诸如int n; cout<<n<<flush;
我们如何设计包装使得cout << speed(9600)的作用等同于setSpeed(cout, 9600)呢?
对于cout<<n这部分代码,我们很清楚其工作流程,这部分的实现是通过重载<<实现的,通过重载<<,可以输出不同类型的值,下面是一个重载<<输出类型Complex的例子
ostream& operator<<(ostream& file, const Complex& z)
{
file << "(" << z.re() << "," << z.im() << ")";
return file;
}
对于cout << flush,实际上上这段代码等同于flush(cout),假设flush是一个函数指针(实际上它有可能是一个函数对象)的话,我们如何实现cout << flush等同于flush(cout)呢?
假设flush函数的定义如下:
ostream& flush(ostream &file)
{
//funtion code
return file;
}
其实同样通过重载<<,我们可以实现将cout << flush等同于flush(cout),这个重载<<形式如下:
ostream& operator<<(ostream& file, ostream& (*func)(osteam&))
{
return (*func)(file);
}
操纵器带有参数的形式
假设有如下代码:
ostream& setSpeed(ostream& file, int n)
{
//funtion code
return file;
}
这个函数的作用是设置流的数据传输速率我们如何设计包装使得cout << speed(9600)的作用等同于setSpeed(cout, 9600)呢?
C++沉思录给出了一种经典实现,代码如下:
class int_fcn_obj
{
public:
int_fcn_obj(ostream& (*f)(ostream&, int), int v)
:func(f), val(v) {}
ostream& operator()(ostream& o) const
{
return (*func)(o, val);
}
private:
ostream& (*func)(ostream& int);
int val;
};
ostream& operator<<(ostream& ofile, const int_fcn_obj& im)
{
return im(ofile);
}
int_fcn_obj speed(int n)
{
return int_fcn_obj(setSpeed, n);
}
C++沉思录作者将上述的speed和flush成为操纵器,把重载的<<称为应用器,针对每一个操纵器,我们可以定制对应的应用器和函数对象,但是实际上不同的<操纵器,应用器,函数对象>对的定义都很相似,所以可以将其提升为模板,上述代码对应的模板如下:
//函数对象模板
template <class stype, class vtype>
class fcn_obj
{
public:
fcn_obj(stype& (*f)(stype&, vtype), vtype v)
:func(f), val(v) {}
stype& operator()(stype& o) const
{
return (*func)(o, val);
}
private:
stype& (*func)(stype& vtype);
vtype val;
};
//应用器模板
template <class stype, class vtype>
stype& operator<<(stype& ofile, const fcn_obj<stype, vtype> & im)
{
return im(ofile);
}
//一个操纵器的例子
fcn_obj<ostream, int> speed(int n)
{
return fcn_obj(setSpeed, n);
}
//使用方法
cout << speed(9600);
总结:C++中的奇迹淫巧确实太多了!!!