我对 C++ 语言有点陌生。我正在编写一个用于记录到文件的实用程序类。它工作得很好,除了现在我想通过使它更方便使用来增强它(例如将字符串流传递给日志函数)。

这是我一直在尝试的,但没有奏效。

定义:
void LogStream( std::stringstream i_Log ){m_FileHandle << i_Log << std::endl;}
称呼:
m_LogObject->LogStream( "MKLBSearchEngine::Search( " << x << ", " << i_Filter << " ) - No Results Found" );

最佳答案

您的解决方案有几个问题。第一个是你
按值传递 stringstream,它不支持复制。你需要
引用。二是在调用现场,返回值operator<< 重载是 ostream& ,而不是 stringstream ,因为stringstream 不是 ostream& 的基类(它是另一种方式
轮),你不能初始化 stringstream (或 stringstream& )
用它。最后,没有 operator<< 需要一个stringstream 作为右手参数,所以语句中的LogStream 函数无法工作。最后,这会有点
反正对用户来说很尴尬。 operator<< 的日志是非成员,
使用 ostream& 非常量引用作为第一个参数,所以你不能
用一个临时的作为左参数来调用它们。 (在您的示例电话中,
当然,你还是忘记创建 std::ostringstream 了;它
不会编译,因为没有将 <<charconst[] 作为其左手操作数的 char const* 重载。)

几乎所有这些问题都有解决方法。某物
喜欢:

void LogStream( std::ostream& text )
{
    std::ostringstream& s = dynamic_cast<std::ostringstream&>(text);
    m_FileHandle << s.str() << std::endl;
}

处理除最后一个以外的所有问题;最后一个必须处理
由客户,例如:
m_LogObject->LogStream( std::ostringstream().flush() << "..." << x );

(对 std::ostream::flush() 的调用返回对
流,可用于进一步初始化 std::ostream&
虽然你不能用临时变量初始化非常量引用,
您可以在其上调用非常量成员函数。)

客户端代码的尴尬使我通常更喜欢
更复杂的解决方案。我定义了一个特殊的 LogStreamer 类,
就像是:
class LogStreamer
{
    boost::shared_ptr< std::ostream > m_collector;
    std::ostream* m_dest;

public:
    LogStreamer( std::ostream& dest )
        , m_collector( new std::ostringstream )
        , m_dest( &dest )
    {
    }
    ~LogStreamer()
    {
        if ( m_collector.unique() ) {
            *m_dest << m_collector->str() << std::endl;
        }
    }
    template <typename T>
    LogStreamer& operator<<( T const& value )
    {
        *m_collector << value;
        return *this;
    }
};


LogStreamer LogStream() { return LogStreamer( m_FileHandle ); }

然后客户端代码可以编写:
m_LogObject->LogStream() << "..." << x;

在我自己的代码中:日志对象始终是单例,调用是
通过一个宏,它将 __FILE____LINE__ 传递给 LogStream()函数,最终目标 ostream 是一个特殊的流缓冲
LogStream() 调用的特殊函数,它接受一个文件名和一个
行号,在开始时输出它们以及时间戳
下一行输出,并缩进所有其他行。一个过滤
streambuf 类似于:
class LogFilter : public std::streambuf
{
    std::streambuf* m_finalDest;
    std::string m_currentHeader;
    bool m_isAtStartOfLine;
protected:
    virtual int overflow( int ch )
    {
        if ( m_isAtStartOfLine ) {
            m_finalDest->sputn( m_currentHeader.data(), m_currentHeader.size() );
            m_currentHeader = "    ";
        }
        m_isAtStartOfLine = (ch == '\n');
        return m_finalDest->sputc( ch );
    }
    virtual int sync()
    {
        return m_finalDest->sync();
    }

public:
    LogFilter( std::streambuf* dest )
        : m_finalDest( dest )
        , m_currentHeader( "" )
        , m_isAtStartOfLine( true )
    {
    }
    void startEntry( char const* filename, int lineNumber )
    {
        std::ostringstream header;
        header << now() << ": " << filename << " (" << lineNumber << "): ";
        m_currentHeader = header.str();
    }
};

(当然,函数 now() 返回一个带有
时间戳。或者 std::string ,并且您已经为 struct tm 编写了 << 。)

关于c++ - std::stringstream 作为参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6280149/

10-16 01:27