我在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
答案 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;
}