在Stroustrup的C ++书中,有一个自定义操纵器接受参数的例子(请参阅附带的代码)。我对如何创建结构感到困惑。特别是,看起来“smanip”的构造函数有两个int参数,一个用于函数指针“ff”,一个用于“ii”。我不明白如何通过使用:
传递int参数来创建结构cout << setprecision(4) << angle;
此外,调用这些函数的顺序是什么,以及如何确定类型参数Ch和Tr?非常感谢。
// manipulator taking arguments
struct smanip{
iso_base& (*f) (ios_base&, int);
int i;
smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};
template<cladd Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
return m.f(os, m.i);
}
ios_base& set_precision(ios_base& s, int n){
return s.setprecision(n); // call the member function
}
inline smanip setprecision(int n){
return smanip(set_precision,n);
}
// usage:
cout << setprecision(4) << angle;
答案 0 :(得分:9)
setprecision(4)
来电
inline smanip setprecision(int n){
return smanip(set_precision,n);
}
从指向smanip
函数的指针和set_precision
创建n
。
struct smanip{
ios_base& (*f) (ios_base&, int);
int i;
smanip(ios_base& (*ff)(ios_base&, int), int ii) : f(ff), i(ii){}
};
smanip
是一个包含指向函数和整数的指针的结构。该函数引用ios_base
引用和int
,并通过引用返回ios_base
。
此时这条线实际上是这样的:
smanip m(&setprecision, 4);
cout << m << (otherstuff);
与此模板匹配:
template<class Ch, class Tr>
ostream<Ch, Tr>& operator<<(ostream<Ch, Tr>& os, smanip& m){
return m.f(os, m.i);
}
编译器可以从左侧的流中推导出Ch
和Tr
。在这种情况下,std::cout
。代码执行m.f(os, m.i)
。这将调用smanip
所持有的函数指针,并将流和smanip
所持的整数传递给它。
ios_base& set_precision(ios_base& s, int n){
return s.setprecision(n); // call the member function
}
这会调用cout.setprecision(n)
。
因此该行转换为:
std::cout.setprecision(4) << angle;
答案 1 :(得分:0)
操纵器仿函数将函数指针和int作为参数,并在内部存储以供以后使用。为了便于阅读,可以在这两个声明中拆分构造函数的签名:
typedef ios_base& (*f_ptr)(ios_base&,int);
smanip( f_ptr f, int )
也就是说,第一个参数是函数指针,第二个参数是值。
从示例代码中的执行顺序开始,首先调用函数setprecision
,该函数将函数指针和值存储在smanip
对象中并返回它。该对象被传递给适当的operator<<
,它在传递参数的当前流上提取并执行存储的函数指针。
// on the calling end
setprecision(4) // --> construct __s = smanip( set_precision, 4 )
(cout << ) // --> passes __s to `operator<<`
// inside operator<<
return m.f( os, m.i ); // calls: set_precision( os, 4 ) (m.f == &set_precision
// m.i == 4 )