C++ 如果我想在c++;或者java什么是单音还是静态

C++ 如果我想在c++;或者java什么是单音还是静态,c++,static,singleton,logging,C++,Static,Singleton,Logging,一般的问题是,我喜欢构建写入单个日志文件的logger类 从我的应用程序中的不同类中,logger类应该是什么 C++中的单类或静态类,您需要单体而不是静态的。C++不允许你控制静态对象的构造和破坏,如果你试图在静态构造之前进行日志记录,那么行为可能是不确定的。 我对Java没有把握。答案当然是“视情况而定” 首先,如果我是你,我不会重新发明轮子,而只是使用它。如果它不能满足您的确切需求,那么您最好扩展log4net中不满足您需求的一个组件(例如定制的loggin源代码),而不是从头开始。其次,

一般的问题是,我喜欢构建写入单个日志文件的logger类 从我的应用程序中的不同类中,logger类应该是什么
C++中的单类或静态类

,您需要单体而不是静态的。C++不允许你控制静态对象的构造和破坏,如果你试图在静态构造之前进行日志记录,那么行为可能是不确定的。 我对Java没有把握。

答案当然是“视情况而定”


首先,如果我是你,我不会重新发明轮子,而只是使用它。如果它不能满足您的确切需求,那么您最好扩展log4net中不满足您需求的一个组件(例如定制的loggin源代码),而不是从头开始。其次,对于一个简单的日志类来说,静态类可能已经足够好了。对于更复杂的东西,单例类可能是一种方法。

不要使用单例或静态,使用依赖注入,即在main()中实例化一个实例,并将对该实例的引用传递给所有依赖类。静态和/或单例几乎从来都不是必需的,通常会导致代码不够优雅

是什么让你认为它应该是这样的?一个可以按需实例化的常规非静态类怎么样?然后将其单个静态实例用作默认记录器。通过这种方式,您可以两全其美:方便地全局访问记录器和测试记录器或临时使用其他记录器的能力

另一个建议是简单地创建一个实例,并将其作为参数传递给类的每个组件,正如@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
不是单身汉。它只是一个C++类的全局实例,它是一个类,它也可以在需要的时候被实例化。C++中的

< P>,你可以用这个习惯用法来进行惰性初始化:

Foo& getInstance()
{
    static Foo instance;
    return instance;
}

我可能会使用单例,但无论如何,都要将其隐藏在函数或宏后面。不要让人打瞌睡

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);

它听起来不像中描述的DI。我不认为显式地向每个函数和类传递一个非关键参数比在必要时请求一个更优雅。为什么这是被否决的?无论它是否符合DI,这都是非常明智的建议。唯一的缺点是在整个程序中传递记录器引用可能有点麻烦+我要求你赔偿。这并不总是最好的策略,但它是一个非常有效的策略,远比在你的应用程序中涂抹单件要好得多。您是否希望每个需要它的类都为日志创建一个新的记录器对象?使用单个“defaultLogger”实例与使用单个实例有何不同?您的解决方案如何比备选方案更好地“测试它的能力”?如果每个人都在实例化自己的记录器,那么您的系统如何“临时使用不同的记录器”?奇怪的是,你得到+4,而disown得到-1。翻译单位之间的globals的构造和破坏顺序是不确定的。如果记录的任何代码使用了从ctor或dtor记录的静态或全局变量,这将导致未定义的behavior.Yep。但如果真是这样,我会说你有一个更根本的问题。一个被称为“为什么有这么多具有复杂初始化/销毁行为的复杂静态对象?”的解决方案不是以单例的形式创建更复杂的静态数据,而是消除一些静态数据。您的程序应该在主函数内部运行,而不是在它之前。