重载运算符将函数指针作为参数,如何检索函数指针的参数

时间:2009-07-16 18:48:34

标签: c++ operator-overloading

我有一个重载的运算符<<试图让它像这样工作

mystream<<hex<<10;

我有重载方法

mytream& operator<<(ios_base& (*m) ios_base&)

每当遇到十六进制时都会调用此方法,因为方法中传递的参数是类型与十六进制相同的函数指针,或者像dec,oct等其他输出操作符一样。

我有两个问题

1)如何检索十六进制将要操作的参数,在本例中为10

2)我怎么知道&lt;&lt;操作符被调用为十六进制而不是其他操纵符函数,如oct和dec

谢谢

5 个答案:

答案 0 :(得分:7)

1)十六进制不对参数10进行操作。<<运算符从左到右关联,这意味着您的代码与以下内容相同:

(mystream<<hex)<<10;

所以你的重载必须返回一个对象,当10移入它时,以十六进制打印(如果没有打印,则在某处写入数据)。正如大家所说,这是通过在流对象本身中保存标志,然后返回*this来完成的。使用原因正是因为“10”尚未可用,因为尚未评估第二个<<。第一个<<操作员调用无法打印任何内容 - 只需要在第二个调用第二个调用时做好准备。

2)hex是一个函数。它可以与其他功能进行比较:

ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
    if (m == hex) {
    } else if (m == oct) {
    } else if (m == dec) {
    }
}

除非您通常不想这样做,否则您需要默认行为,例如:

ostream &operator<<(ostream &s, ios_base& (*m)(ios_base &)) {
    return m(s);
}

(我可能错了,我从来没有看过实现,但一般的想法是操作符调用操纵器函数,操纵器(名称中的线索)操纵流)。

std::hex在其参数上设置std::ios::hex格式标志。然后在operator<<(int)覆盖中,如果有,请通过调用flags()检查格式标记。

3)采用参数的机械手也是函数,但它们的返回类型是未指定的,这意味着它取决于实现。查看我的gcc iomanip标题,setw返回_Setwsetprecision返回_Setprecision,依此类推。 The Apache library does it differently,更像是无法操纵者。您可以使用参数化操纵器进行的唯一操作是将它们应用于operator<<的iostream,它们没有已定义的成员函数或自己的运算符。

就像hex一样,要处理setw,你应该继承std::ios_base,依靠你图书馆提供的operator<<实现,然后当你来格式化数据,使用width()上的precision()ios_base等函数检查自己的宽度,精度等。

那就是说,如果出于某种奇怪的原因你需要拦截这些操纵者的标准operator<<,你可以沿着这些方向一起躲避:

template <typename SManip>
mystream &operator<<(mystream &s, SManip m) {
    stringstream ss;
    // set the state of ss to match that of s
    ss.width(s.width());
    ss.precision(s.precision());
    // etc
    ss << m;
    // set the state of s to match that of ss
    s.width(ss.width());
    s.precision(ss.precision());
    // etc
    return s;
}
但是,我确实认为这是一个小屋。你真的不应该干扰流操作符,只需让你的基类完成工作并查找结果。

答案 1 :(得分:0)

使用operator<<hexoct调用dec时,请在mystream对象中设置一个标记。使用数字调用operator<<时,请检查是否设置了这些标志中的任何一个。如果是这样,将数字转换为十六进制/八进制/十进制并显示它。

答案 2 :(得分:0)

在回答第二个问题时,参数m是指向操纵器功能的指针。您可以检查它是否为空,然后调用该函数,传递*this。正如Zifre建议的那样,hex()就像在传递的流对象中设置标志一样简单。然后在处理整数时,检查流对象中的标志是否已设置,并相应地输出。

这是标准库实现其操纵器功能的方式。

答案 3 :(得分:0)

在您的示例中,十六进制操作流(更改状态)流,而不是以下参数。 hex没有概念,或与其他&lt;&lt;调用

看看如何实施其他io操纵器将有很长的路要走。

答案 4 :(得分:0)

你应该操纵ios_base :: flags

http://www.cplusplus.com/reference/iostream/ios_base/flags/

这是标准的十六进制文件。