【问题标题】:An overloaded operator takes function pointer as parameter, how do i retrieve arguments of function pointer重载运算符将函数指针作为参数,我如何检索函数指针的参数
【发布时间】:2009-07-16 18:48:33
【问题描述】:

我有一个重载的运算符

mystream<<hex<<10;

我有重载方法

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

每当遇到 hex 时都会调用此方法,因为方法中传递的参数是与 hex 类型相同的函数指针,或者类似于 dec、oct 等其他输出操纵器。

我有两个问题

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

2) 我怎么知道

谢谢

【问题讨论】:

    标签: c++ operator-overloading


    【解决方案1】:

    1) 十六进制没有对参数10进行操作。&lt;&lt;操作符从左到右关联,也就是说你的代码是一样的:

    (mystream<<hex)<<10;
    

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

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

    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&lt;&lt;(int) 覆盖中,如果有,请调用flags() 检查格式标志。

    3) 带有参数的操纵器也是函数,但它们的返回类型是未指定的,这意味着它取决于实现。查看我的 gcc iomanip 标头,setw 返回 _Setw,setprecision 返回 _Setprecision,等等。 The Apache library does it differently,更像是无参数操纵器。您可以对参数化操纵器进行可移植的唯一操作是将它们应用到带有 operator&lt;&lt; 的 iostream,它们没有定义自己的成员函数或运算符。

    所以就像hex,要处理setw,你应该继承std::ios_base,依靠你的库提供的operator&lt;&lt;实现,然后当你格式化你的数据时,检查你自己的宽度,精度等,使用width()、precision()等函数在ios_base上。

    也就是说,如果出于某种奇怪的原因您需要截获这些操纵器的标准 operator&lt;&lt;,您可能会按照以下思路一起躲避:

    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;
    }
    

    不过,我确实认为这是一个麻烦。您实际上不应该干预流操纵器,只需让您的基类完成工作并查找结果即可。

    【讨论】:

    • 谢谢,你能帮忙看看如何处理像 setw 和 setprecesion 这样的操纵器
    • 致电width() 和precision() 以及flags()。详情见上。
    【解决方案2】:

    当operator&lt;&lt; 被hex 或oct 或dec 调用时,在mystream 对象中设置一个标志。当使用数字调用operator&lt;&lt; 时,检查是否设置了这些标志中的任何一个。如果是这样,将数字转换为十六进制/八进制/十进制并显示。

    【讨论】:

    • 这是一个递归答案“当 operator
    • 你应该在 another 重载的运算符函数中得到数字,一个得到 int 的函数
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      在您的示例中,十六进制对流进行操作(更改其状态),而不是以下参数。 hex 与其他

      看看其他 io 操纵器是如何实现的,这对于清理事情大有帮助。

      【讨论】:

        【解决方案5】:

        你应该在操纵 ios_base::flags

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

        这是标准十六进制的作用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-29
          • 2011-02-04
          • 2012-03-07
          • 2014-07-16
          • 1970-01-01
          相关资源
          最近更新 更多