kfm*_*e04 39 c++ singleton c++11
我目前的实施,简化:
#include <string>
#include <memory>
class Log
{
public:
~Log() {
// closing file-descriptors, etc...
}
static void LogMsg( const std::string& msg )
{
static std::unique_ptr<Log> g_singleton;
if ( !g_singleton.get() )
g_singleton.reset( new Log );
g_singleton->logMsg( msg );
}
private:
Log() { }
void logMsg( const std::string& msg ) {
// do work
}
};
Run Code Online (Sandbox Code Playgroud)
总的来说,我对此实现感到满意,因为:
但是,负面因素是:
所以这里是我的问题针对那些成功从他们的C++代码中驱逐所有单例的开发人员:
我想避免在我的代码中传递一个Log实例,如果可能的话 - 注意:我问,因为,如果有一个好的,合理的选择,我也想从我的代码中驱除所有Singletons.
Mat*_* M. 42
第一:使用std::unique_ptr
是不必要的:
void Log::LogMsg(std::string const& s) {
static Log L;
L.log(s);
}
Run Code Online (Sandbox Code Playgroud)
生成完全相同的延迟初始化和清理语义,而不会引入所有语法噪声(和冗余测试).
现在已经不在了......
你的课非常简单.您可能希望构建稍微复杂的版本,日志消息的典型要求是:
在消息本身之上.
因此,完全可以设想具有不同参数的多个对象:
// LogSink is a backend consuming preformatted messages
// there can be several different instances depending on where
// to send the data
class Logger {
public:
Logger(Level l, LogSink& ls);
void operator()(std::string const& message,
char const* function,
char const* file,
int line);
private:
Level _level;
LogSink& _sink;
};
Run Code Online (Sandbox Code Playgroud)
为方便起见,您通常将访问包装在宏中:
#define LOG(Logger_, Message_) \
Logger_( \
static_cast<std::ostringstream&>( \
std::ostringstream().flush() << Message_ \
).str(), \
__FUNCTION__, \
__FILE__, \
__LINE__ \
);
Run Code Online (Sandbox Code Playgroud)
现在,我们可以创建一个简单的详细记录器:
Logger& Debug() {
static Logger logger(Level::Debug, Console);
return logger;
}
#ifdef NDEBUG
# define LOG_DEBUG(_) do {} while(0)
#else
# define LOG_DEBUG(Message_) LOG(Debug(), Message_)
#endif
Run Code Online (Sandbox Code Playgroud)
并方便地使用它:
int foo(int a, int b) {
int result = a + b;
LOG_DEBUG("a = " << a << ", b = " << b << " --> result = " << result)
return result;
}
Run Code Online (Sandbox Code Playgroud)
这个咆哮的目的?并非所有全球需求都是独一无二的.单身人士的独特性通常是无用的.
注意:如果神奇的一点涉及std::ostringstream
吓到你,这是正常的,请看这个问题
jal*_*alf 12
我会选择简单实用的解决方案:
您想要一个全球可访问的解决方案.在大多数情况下,我尽量避免使用全局变量,但对于记录器,让我们面对它,这通常是不切实际的.
因此,我们确实需要一些全球可访问的东西.
但是,我们不希望单身人士给予额外的"只有一个"限制.您的某些单元测试可能希望实例化自己的私有记录器.其他人可能想要替换全局记录器.
所以让它成为全球性的.一个简单的旧简单全局变量.
诚然,这仍然没有完全解决单元测试的问题,但我们不能总是拥有我们想要的一切.;)
正如评论中所指出的,你需要考虑全局变量的初始化顺序,在C++中,它是部分未定义的.
在我的代码中,这通常不是问题,因为我很少有一个以上的全局(我的记录器),并且我严格遵守永远不允许全局变量依赖于彼此的规则.
但至少你必须考虑这个问题.
Dav*_*rle 11
我非常喜欢以下界面,因为它使用流媒体.当然,您可以添加频道,时间和线程信息.另一种可能的扩展是使用__FILE__
和__LINE__
宏并将其作为参数添加到构造函数中.如果您不喜欢流语法,甚至可以添加可变参数模板函数.如果要存储某些配置,可以将它们添加到某些静态变量中.
#include <iostream>
#include <sstream>
class LogLine {
public:
LogLine(std::ostream& out = std::cout) : m_Out(out) {}
~LogLine() {
m_Stream << "\n";
m_Out << m_Stream.rdbuf();
m_Out.flush();
}
template <class T>
LogLine& operator<<(const T& thing) { m_Stream << thing; return *this; }
private:
std::stringstream m_Stream;
std::ostream& m_Out;
//static LogFilter...
};
int main(int argc, char *argv[])
{
LogLine() << "LogLine " << 4 << " the win....";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
19069 次 |
最近记录: |