代码之家  ›  专栏  ›  技术社区  ›  Patrick

类的自定义流操纵器

  •  0
  • Patrick  · 技术社区  · 15 年前

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

    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 回复  |  直到 15 年前
        1
  •  4
  •   robson3.14    15 年前

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

     class CAudit
     {
      //...other details here as in original question
    
      CAudit& operator << (CAudit & (*func)(CAudit &))
      {
            return func(*this);
      }
     };
    
     CAudit audit;
     audit << "some text" << CAudit::write;
    
        2
  •  2
  •   Tadeusz Kopec for Ukraine yespbs    15 年前

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

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

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

    CAudit& operator<< (CAudit& ( *pf )(CAudit& audit))
    {
      return (*pf)(audit);
    }
    
        3
  •  1
  •   sbi    15 年前

    难道这不是

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

    做你想做的?

        4
  •  1
  •   iain    15 年前

    我做了一些非常类似的跟踪,但是使用 stringstream . 这确保所有第三方 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 语句意味着您没有构建跟踪线的开销,除非您实际需要它。

    归还 ostream 通过 stream() 方法使这对全局成员函数有效,因为匿名对象不能作为非常量引用参数传递。