【问题标题】:C++: Overloading << operator with function pointersC++:用函数指针重载 << 运算符
【发布时间】:2014-12-24 15:29:41
【问题描述】:

我有一个“stampstream”类,它本质上是为了像“cout”一样工作。接下来的两个函数在类之外。这是有效的部分。

class stampstream: public std::ostream
{
    //code
    stampstream& operator<<(stampstream& (*x)(void))
    {
        //code
    }
    //code
};

stampstream& endr()
{
    //nocode
}

stampstream& (*endrow)(void)=endr;

主要:

stampstream s;
s << "teststring1" << endrow;

请注意,“endrow”本质上是“endl”。这部分工作得很好,编译并使用正确的输出执行。 现在,我正在尝试用另一个可能的 row(int) 函数重载

class stampstream: public std::ostream
{
    //code
    stampstream& operator<<(stampstream& (*r)(int y))
    {
        //code
    }
    //code
};

stampstream& ro(int y)
{
    //nocode
}

stampstream& (*row)(int)=ro;

主要:

s << "teststring2" << row(5);

这是我得到的错误:

error: invalid user-defined conversion from ‘stampstream’ to ‘stampstream& (*)(int)’ [-fpermissive]

我对行做错了什么?

【问题讨论】:

  • 提示:row(5) 的类型是什么?
  • 行是带有int参数的stampstream类型
  • 而 当你调用它时,就像你说 row(5) 时所做的那样,它会返回什么? stampstream,不是指向函数的指针。
  • 它不返回任何东西,但 endrow 也不返回,而且效果很好。是的,它应该是一个 stampstream 类型的返回。
  • 是“函数调用运算符”。它出现在函数或函数指针的右侧,立即调用它,并计算函数调用的结果(返回)。如果你想让s &lt;&lt; row(5) 工作,那么row(5) 需要返回operator&lt;&lt; 可以接受的东西。

标签: c++ operator-overloading


【解决方案1】:

问题在于

s << "teststring2" << row(5);

函数调用的优先级高于&lt;&lt;,因此这会调用函数row 指向,然后尝试将其返回值(stampstream &amp;)传递给operator&lt;&lt;。

你想要的是

s << "teststring2" << row;

这不会调用函数,而是将指针传递给operator&lt;&lt;。在 that 函数中,当你想调用 x 时,你需要提供参数。

听起来你试图做的是有一个函数row,它创建一个函子对象,然后你可以将它传递给operator&lt;&lt;。你可以在 C++11 中使用 lambda 来做到这一点:

class stampstream: public std::ostream
{
    //code
    stampstream& operator<<(std::function<stampstream&(void)> r)
    {
        //code
    }
    //code
};

std::function<stampstream&(void)> row(int x)
{
    return [x]()->stampstream & {
        //code
    }
}

你可以这样称呼:

s << "teststring2" << row(5);

首先调用row,它构造一个lambda并返回它(但还没有运行其中的代码)。函子被传递给operator&lt;&lt;,当该函数调用r时,它会调用lambda中的代码(可以参考x参数,它是值绑定的,所以复制到lambda中。)

【讨论】:

  • 我遇到了一堆错误,但主要是这让我回到:错误:'row'没有在这个范围内声明......因为我假设它没有stampstream类型.
  • '一堆错误'可能表明你的编译器不支持 C++11
  • 我正在使用 g++ 编译器。我试过 g++ -std=c++11... 这就是我得到的:错误:将 'operator r )。错误:预期的“;”在成员声明的末尾。错误:在“ row(int x)。 stampstream.cpp:在函数“int main()”中:错误:“row”未在此范围内声明 s
  • @Prasad 你还需要#include &lt;functional&gt;。
  • 谢谢!它编译..现在我想知道在 return [x]()->stampstream & {... 我想要做的事情需要一个私有类成员数据。另外,如何在重载
【解决方案2】:

由于 Chris 已经回答了您的问题,我想向您推荐您当前方法的替代方案:

  1. 你的stampstream 类应该使用一个专门的std::streambuf 来写出overflow() 中的戳记。无需扩展 std::ostream 并重新实现输入运算符。有关如何执行此操作的示例,see this thread。

  2. 您似乎在使用 endrow 和 row 之类的操纵器。对于在调用站点不接受参数的操纵器,已经存在运算符重载。您可以让endrow 获取并返回std::ostream&amp; 类型的对象。对于row,你可以让它返回一个重载插入器的类以允许你想要的语法:

    struct row_impl
    {
        row_impl(int row) : row(row) { }
        // Write out the row and return the stream
        friend std::ostream& operator<<(std::ostream& os, row_impl const& rimpl);
    private:
        int row;
    };
    
    std::ostream& operator<<(std::ostream& os, row_impl const& rimpl)
    {
        // This is where the code for your original row() function goes
    }
    
    // write out to and return the stampstream instance
    std::ostream& endrow(std::ostream& os);
    
    row_impl row(int row)
    {
        return row_impl(row);
    }
    

    现在s &lt;&lt; endrow 和s &lt;&lt; row(5) 可以工作,而无需向您的stampstream 类添加任何内容。

【讨论】:

  • 这是最初提出的解决方案。我想交替尝试。但是谢谢你:)
猜你喜欢
  • 2013-08-18
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
  • 2015-08-12
  • 1970-01-01
  • 1970-01-01
  • 2020-10-14
相关资源
最近更新 更多