0

我正在尝试编写一个简单的审计类,它通过运算符 << 接受输入,并在收到这样的自定义操纵器后编写审计:

class CAudit
{
public:
    //needs to be templated
    CAudit& operator << ( LPCSTR data ) {
        audittext << data;
        return *this;
    }

    //attempted manipulator
    static CAudit& write(CAudit& audit) { 
        //write contents of audittext to audit and clear it
        return audit; 
    }

private:
    std::stringstream audittext;
};

//to be used like
CAudit audit;
audit << "Data " << data << " received at " << time << CAudit::write;

我认识到我的代码中的重载运算符不会返回流对象,但我想知道是否仍然可以使用类似语法的操纵器。目前,编译器将“<<”视为二进制右移运算符。

感谢您的任何意见,帕特里克

4

4 回答 4

5

要使其工作,您必须为函数添加运算符 << 的重载,而不是从中调用函数:

 class CAudit
 {
  //...other details here as in original question

  CAudit& operator << (CAudit & (*func)(CAudit &))
  {
        return func(*this);
  }
 };

 CAudit audit;
 audit << "some text" << CAudit::write;
于 2009-08-25T14:40:46.850 回答
2

二进制移位运算符和流运算符是相同的运算符。为你的类重载 operator+ 在 std::cout 上写“Hello world”是完全合法的(尽管这是一个非常糟糕的主意)。与 C++ 标准作者决定将流的 operator<< 重载为写入流的方式相同。
你没有写清楚你的问题是什么。我的猜测是编译错误。在这种情况下,最好的办法是引用错误消息。如果我是对的,问题是,您只为 LPCSTR 定义了 operator<<,然后您希望它在右侧工作函数对象。
你使用“操纵者”这个词,但你误解了一些东西。流的操纵器(来自 STL 的流)是一个函数,它对写入的流执行一些操作。它之所以有效,只是因为这种重载:

ostream& operator<< (ostream& ( *pf )(ostream&));

它接受一个函数并将其应用于流。
同样,您需要:

CAudit& operator<< (CAudit& ( *pf )(CAudit& audit))
{
  return (*pf)(audit);
}
于 2009-08-25T14:46:02.177 回答
1

这不

class CAudit
{
public:
    template< typename T >
    CAudit& operator<<( const T& data )
    {
        audittext << data;
        return *this;
    }

    class write {};

    void operator<<( const write& data )
    {
        /* whatever */
    }

private:
    std::stringstream audittext;
};

做你想做的事?

于 2009-08-25T14:35:55.967 回答
1

我为跟踪做了非常相似的事情,但使用stringstream. 这可确保所有第 3 方operator << ()和操纵者都能正常工作。我还使用析构函数而不是客户写操纵器。

class DebugStream
{
public:
    DebugStream(short level, const char * file, int line) {
        sstream << "L" << level << "\t" << file << "\t" << line << "\t";
    }
    ~DebugStream() { write(sstream.str()); }

    std::ostream & stream() { return sstream; }
private:
    std::stringstream sstream;

    DebugStream(const DebugStream &);
    DebugStream & operator=(const DebugStream &);
};

然后可以使用一些宏:

#define DBG_ERROR if (1<=dbg_level()) DebugStream(1, __FILE__, __LINE__).stream()
#define DBG_INFO  if (2<=dbg_level()) DebugStream(2, __FILE__, __LINE__).stream()

代码只使用宏

DBG_INFO << "print some debug information";

您不需要特定的写入操纵器即可将数据刷新到日志文件。当匿名DebugStream对象超出范围时(一旦控制离开行),内容就会自动写入。

尽管在这种情况下我通常避免使用宏,但使用该if语句意味着您没有构建跟踪线的开销,除非您确实需要它。

返回ostreamviastream()方法可以使它适用于全局成员函数,因为匿名对象不能作为非常量引用参数传递。

于 2009-08-25T15:36:06.843 回答