重新定义运营商<

时间:2011-11-10 18:55:14

标签: c++ linux pointers singleton operator-overloading

我在Linux上有一个C ++类,允许我在控制台上显示消息,具体取决于应用程序的运行位置。如果它在我的计算机中工作,则以控制台模式显示消息。否则,所有内容都会记录在文本文件中以供日后查看。我创建了一个外部对象来使用它。我想尝试让这个班级成为单身人士,但没有成功。当我编译程序时,我有这个错误:

  

错误:类型'Log *'和'const char [12]'到二进制'运算符<<'

的操作数无效

还有:

  

错误:'operator<<'不匹配在'logOutput'<< Buffer_T ....

我想要你的意见。提前感谢您的关注。

我的功能课目前

typedef std::vector<unsigned char> Buffer_T;

class Log
{
public:
    Log();
    virtual ~Log();

    void init()
    {
    #indef FriendlyArm
        output = new ofstream("/home/arm/Log.txt");
    #else
        output = &cout;
    #endif
    }


    template<typename T>
    Log operator<<( T const& value )
    {
        (*output) << value;
        return *this;
    }

    Log& operator<<( std::ostream&(*f)(std::ostream&) )
    {
        (*output) << f;
        return *this;
    }

    Log& operator<<(Buffer_T& Buf)
    {
        if( Buf.size() > 0 )
        {
            for( unsigned int i = 0; i < Buf.size(); i++ )
            {
                if( Buf[i] >= 32 && Buf[i] <= 127 )
                {
                    (*output) << Buf[i];
                }
                else
                {
                    (*output) << "0x" << std::setfill( '0' ) << std::hex << std::setw( 2 ) << unsigned( Buf[i] );
                }
            }
        }
        return *this;
    }


private:
    ostream *output;
};
#endif /* LOG_H_ */

这是我尝试单身人士

typedef std::vector<unsigned char> Buffer_T;

class Log
{
    public:
        static Log *createOrGet()
        {
            if(_unique == NULL)
            {
                _unique = new Log();
            }

            return _unique;
        }

        static void kill()
        {
            if(_unique != NULL)
            {
                delete _unique;
                _unique = NULL;
            }
        }

        void init()
        {
        #indef FriendlyArm
            output = new ofstream("/home/arm/Log.txt");
        #else
            output = &cout;
        #endif
        }

        template<typename T>
        Log operator<<( T const& value )
        {
            (*output) << value;
            return *this;
        }

        Log& operator<<( std::ostream&(*f)(std::ostream&) )
        {
            (*output) << f;
            return *this;
        }

        Log& operator<<(Buffer_T& Buf)
        {
            if( Buf.size() > 0 )
            {
                for( unsigned int i = 0; i < Buf.size(); i++ )
                {
                    if( Buf[i] >= 32 && Buf[i] <= 127 )
                    {
                         (*output) << Buf[i];
                    }
                    else
                    {
                        (*output) << "0x" << std::setfill( '0' ) << std::hex << std::setw( 2 ) << unsigned( Buf[i] );
                    }
                }
            }
            return *this;
        }

    private:
        Log();
        virtual ~Log();
        static Log *_unique;
        ostream *output;
};
Log *Log::_unique = NULL;
#endif

3 个答案:

答案 0 :(得分:1)

重要提示:不要采取错误的方式,但是你犯了一些错误,表明你不是很有经验,单身者很难正确使用。在记录器的情况下,他们没问题,只需确保始终将它们作为最后的手段使用。

我没有时间回顾为什么operator<<不适合你,但这里有一些关于如何改进你的单身人士的提示(你似乎也在寻求建议)。< / p>

实例功能

// The idiomatic way is to call this function 'Instance',
// but this doesn't really matter.
static Log& Instance() {
    static Log obj;
    return obj;
}

那叫做迈耶的单身人士。对于单线程应用程序,它很棒:实例在第一次调用函数时创建,自动在应用程序关闭时被销毁(您不需要kill函数)。

您的私有虚拟析构函数

我注意到你有一个私有虚拟析构函数。当类中至少有一个其他虚函数时,您只需要一个虚拟析构函数。不是这种情况;使析构函数非虚拟。

实施单个实例

你使构造函数变得私有 - 这很好,你阻止我直接创建单例的多个实例。但是你并没有阻止我复制现有的单身人士。还要防止您还需要使CopyConstructor和AssignmentOperator非公开:

protected:
  Log();
  Log(const Log&); // CopyConstructor
  Log& operator=(const Log&); // AssignmentOperator
  ~Log();

(析构函数也应该是私有的,以防止我删除该类的唯一实例。)

另请注意我制作了protected,而不是public。如果你不知道差异,请查阅(没有足够的空间来解释)。我创建了它们protected,因此如果需要,您可以继承Log类。

答案 1 :(得分:0)

来自你的评论:

  Log *logOutput;
  logOutput = Log::createOrGet();
  logOutput << "ProcessCommand called" << endl;
  logOutput << Data << endl;

问题:您的Log::createOrGet()会返回Log*,而定义的operator<<会收到Log(请注意缺少'*')。

有两种解决方案:

  • 到处使用*logOutput。这很麻烦,所以最好使用替代方案:
  • 将定义更改为Log& logOutput;并调整Log::createOrGet()以返回Log&(最后一点:请参阅Paul Manta对Instance()的定义)

不要忘记阅读并理解保罗曼塔的言论!

注意:虽然这样可以解决引用的错误消息,但这不会解决代码中的其他问题。重写代码似乎是唯一的解决方案;请看Paul Manta的回答(再次)提出建议。

答案 2 :(得分:0)

在OP的评论中,您发布了以下测试工具:

int main()
{
    Log *logOutput; 
    logOutput = Log::createOrGet(); 
    logOutput << "ProcessCommand called";
    logOutput << Data << endl; // I dont know what Data is, so I commented this out
}

您需要取消引用logOutput才能流式传输。否则,您将流式传输到指向日志的指针,而不是指向日志本身。

但你也有其他问题。你的方法模板:

template<typename T>
Log operator<<( T const& value )
{
    (*output) << value;
    return *this;
}

按值返回Log,这将导致临时值在超出范围时被销毁,但Log::~Log被声明为private,因此无法访问。

更改您的operator<<以通过引用返回Log

template<typename T>
const Log& operator<<( T const& value ) const
{
    (*output) << value;
    return *this;
}

Log& operator<<( std::ostream&(*f)(std::ostream&) )
{
    (*output) << f;
    return *this;
}

Log& operator<<(Buffer_T& Buf) 
{
    if( Buf.size() > 0 )
    {
        for( unsigned int i = 0; i < Buf.size(); i++ )
        {
            if( Buf[i] >= 32 && Buf[i] <= 127 )
            {
                    (*output) << Buf[i];
            }
            else
            {
                (*output) << "0x" << std::setfill( '0' ) << std::hex << std::setw( 2 ) << unsigned( Buf[i] );
            }
        }
    }
    return *this;
}