单例日志 class 中运算符 << 的问题
Problems with operator << in a Singleton Log class
我正在尝试实现 Meyers Singleton 日志 class,它使用 '<<' 运算符来允许这样的事情:
int _tmain(int argc, TCHAR* argv[])
{
SLog& log = SLog::getLogInstance();
log << output::screen << "Test" << endl;
}
[是的,我知道 _tmain()
是一个可怕的 Windows hack - 我只是想学习这些东西,这是我现在推送 unicode 的最简单方法;以后再担心跨平台的问题]
我的问题是我的模板函数从来没有被调用过;它似乎总是调用基数 wostream
。以下是有关实施的更多信息:
--SLog.h--
enum class output : int
{
screen = 0,
file,
both
};
class SLog
{
private:
TOSTREAM* m_pO;
output m_Output;
SLog(); // Private ctor; no instantiation allowed
~SLog(); // Private dtor; no way to kill it
SLog(SLog const&) {}; // Private copy ctor; copying is a no-no
SLog& operator = (SLog const&) {}; // Private - no assignations
public:
template<typename T>
TOSTREAM& operator<<(const T& statement)
{
switch (m_Output)
{
case output::file:
if( NULL != m_pO )
*m_pO << statement;
break;
case output::both:
TOUT << statement;
if( NULL != m_pO )
*m_pO << statement;
break;
default: // default to screen
TOUT << statement << " like a boss...";
break;
}
if (NULL != m_pO)
return *m_pO;
else
return TOUT;
};
TOSTREAM& operator<<(const output& statement);
static SLog& getLogInstance();
};
这里是 SLog.cpp:
SLog & SLog::getLogInstance()
{
static SLog log;
return log;
}
SLog::SLog()
{
m_pO = new TOSTREAM(TOUT.rdbuf());
// Initially set the output to go to the screen
m_Output = output::screen;
}
SLog::~SLog()
{
// Is our logging output stream still good?
if (NULL != m_pO)
{
m_pO->flush(); // flush it, in case there's still output
delete m_pO; // free the memory I allocated in the ctor
m_pO = NULL; // Set it to null to be sure we can't use it
}
}
TOSTREAM & SLog::operator<<(const output & statement)
{
m_Output = statement;
if (NULL != m_pO)
return *m_pO;
else
return TOUT;
}
我在这里定义了 TOUT、TOSTREAM 等:
#if defined(UNICODE) || defined(_UNICODE)
#define TERR std::wcerr
#define TOUT std::wcout
#define TSTRING std::wstring
#define TSSTREAM std::wstringstream
#define TOSTREAM std::wostream
#define TOFSTREAM std::wofstream
#define TNPOS std::wstring::npos
#define SPRINTF swprintf_s
#else
#define TERR std::cerr
#define TOUT std::cout
#define TSTRING std::string
#define TSSTREAM std::stringstream
#define TOSTREAM std::ostream
#define TOFSTREAM std::ofstream
#define TNPOS std::string::npos
#define SPRINTF sprintf_s
#endif
[添加 << " like a boss..." <<
只是为了看看我是否正在调用我的函数,因为我尝试了各种方法让它打印出来;它从来没有,当我设置断点并遍历时,我只经历了基础 wostream
实现...]
所以,我显然不是我认为的 C++ 程序员;我在这里做错了什么??
看来你忘了测试小案例了。
log << "Test" << endl;
产出
Test like a boss...
如你所料。
但是
log << "Test" << " more test" << endl;
产出
Test like a boss... more test
您的流插入运算符 return TOSTREAM &
,因此只有第一项进入 SLog
。
他们应该return一个SLog&
,即*this
。
SLog & SLog::operator<<(const output & statement)
{
m_Output = statement;
return *this;
}
其他接线员作为练习离开了。
我正在尝试实现 Meyers Singleton 日志 class,它使用 '<<' 运算符来允许这样的事情:
int _tmain(int argc, TCHAR* argv[])
{
SLog& log = SLog::getLogInstance();
log << output::screen << "Test" << endl;
}
[是的,我知道 _tmain()
是一个可怕的 Windows hack - 我只是想学习这些东西,这是我现在推送 unicode 的最简单方法;以后再担心跨平台的问题]
我的问题是我的模板函数从来没有被调用过;它似乎总是调用基数 wostream
。以下是有关实施的更多信息:
--SLog.h--
enum class output : int
{
screen = 0,
file,
both
};
class SLog
{
private:
TOSTREAM* m_pO;
output m_Output;
SLog(); // Private ctor; no instantiation allowed
~SLog(); // Private dtor; no way to kill it
SLog(SLog const&) {}; // Private copy ctor; copying is a no-no
SLog& operator = (SLog const&) {}; // Private - no assignations
public:
template<typename T>
TOSTREAM& operator<<(const T& statement)
{
switch (m_Output)
{
case output::file:
if( NULL != m_pO )
*m_pO << statement;
break;
case output::both:
TOUT << statement;
if( NULL != m_pO )
*m_pO << statement;
break;
default: // default to screen
TOUT << statement << " like a boss...";
break;
}
if (NULL != m_pO)
return *m_pO;
else
return TOUT;
};
TOSTREAM& operator<<(const output& statement);
static SLog& getLogInstance();
};
这里是 SLog.cpp:
SLog & SLog::getLogInstance()
{
static SLog log;
return log;
}
SLog::SLog()
{
m_pO = new TOSTREAM(TOUT.rdbuf());
// Initially set the output to go to the screen
m_Output = output::screen;
}
SLog::~SLog()
{
// Is our logging output stream still good?
if (NULL != m_pO)
{
m_pO->flush(); // flush it, in case there's still output
delete m_pO; // free the memory I allocated in the ctor
m_pO = NULL; // Set it to null to be sure we can't use it
}
}
TOSTREAM & SLog::operator<<(const output & statement)
{
m_Output = statement;
if (NULL != m_pO)
return *m_pO;
else
return TOUT;
}
我在这里定义了 TOUT、TOSTREAM 等:
#if defined(UNICODE) || defined(_UNICODE)
#define TERR std::wcerr
#define TOUT std::wcout
#define TSTRING std::wstring
#define TSSTREAM std::wstringstream
#define TOSTREAM std::wostream
#define TOFSTREAM std::wofstream
#define TNPOS std::wstring::npos
#define SPRINTF swprintf_s
#else
#define TERR std::cerr
#define TOUT std::cout
#define TSTRING std::string
#define TSSTREAM std::stringstream
#define TOSTREAM std::ostream
#define TOFSTREAM std::ofstream
#define TNPOS std::string::npos
#define SPRINTF sprintf_s
#endif
[添加 << " like a boss..." <<
只是为了看看我是否正在调用我的函数,因为我尝试了各种方法让它打印出来;它从来没有,当我设置断点并遍历时,我只经历了基础 wostream
实现...]
所以,我显然不是我认为的 C++ 程序员;我在这里做错了什么??
看来你忘了测试小案例了。
log << "Test" << endl;
产出
Test like a boss...
如你所料。
但是
log << "Test" << " more test" << endl;
产出
Test like a boss... more test
您的流插入运算符 return TOSTREAM &
,因此只有第一项进入 SLog
。
他们应该return一个SLog&
,即*this
。
SLog & SLog::operator<<(const output & statement)
{
m_Output = statement;
return *this;
}
其他接线员作为练习离开了。