【发布时间】:2011-02-04 04:27:14
【问题描述】:
一般问题是我喜欢构建写入单个日志文件的记录器类 来自我的应用程序中的不同类,记录器类应该是什么 单调或静态类
【问题讨论】:
标签: c++ static singleton logging
一般问题是我喜欢构建写入单个日志文件的记录器类 来自我的应用程序中的不同类,记录器类应该是什么 单调或静态类
【问题讨论】:
标签: c++ static singleton logging
是什么让您认为两者都应该如此?可以按需实例化的常规非静态类怎么样?然后将它的单个静态 instance 用作默认记录器。这样您就可以两全其美:方便地全局访问记录器和测试记录器或临时使用不同记录器的能力。
另一个建议是简单地创建一个实例并将其作为参数传递给类的每个组件,正如@disown 所建议的那样。
但是,如果您将类本身设为静态或单例,那您就是在自取其辱。
编辑
例如,回应@Stephen 的评论:
// define a logger class, a perfectly ordinary class, not a singleton, and without all static members
class Logger {
// ....
};
// create a single global *instance* of this class
Logger defaultLog;
void foo() {
// and now use the globally visible instance
defaultLog.Log("hello");
// or create a new one if that's what we need:
Logger newlog;
newlog.Log("hello");
}
没有魔法。这正是标准库所做的。 std::cout 不是单身人士。它只是类std::ostream 的全局实例,该类也可以在需要时正常实例化。
【讨论】:
在 C++ 中,您需要的是单例而不是静态的。 C++ 不允许您控制静态对象的构造和销毁顺序,如果您在构造静态对象之前尝试记录,则行为可能是未定义的。
我不确定 Java。
【讨论】:
答案当然是“视情况而定”。
首先,如果我是你,我不会重新发明轮子,只使用Log4j。如果它不能满足您的确切要求,您最好扩展 log4net 的一个不满足您需求的组件(例如自定义登录源),而不是从头开始。其次,静态类对于简单的日志记录类可能已经足够了。对于更复杂的事情,单例类可能是要走的路。
【讨论】:
在 C++ 中,您可以使用以下惯用语进行延迟初始化:
Foo& getInstance()
{
static Foo instance;
return instance;
}
【讨论】:
不要使用单例或静态,使用依赖注入,即在 main() 中实例化一个实例,并将对该实例的引用传递给所有依赖类。静态和/或单例几乎从不需要,而且通常会导致代码不太优雅。
【讨论】:
我可能会使用单例,但无论哪种方式,都将其隐藏在函数或宏后面。不要让人打字
MySuperSpectacularLogger::GetInstance()->Log("adssdf");
改为使用:
void Log(cpnst string& msg) {
MySuperSpectacularLogger::GetInstance()->Log(msg);
}
甚至更好:
// Logs 'msg' with the filename and line number that generates it.
#define LOG(msg) \
MySuperSpectacularLogger::GetInstance()->Log(__FILE__, __LINE__, msg);
【讨论】: