C++ 在c+中记录时出错+;
我实现了一个非常简单的(错误)记录器类。看起来是这样的:C++ 在c+中记录时出错+;,c++,C++,我实现了一个非常简单的(错误)记录器类。看起来是这样的: #pragma once #include <string> extern const char* LOG_DEFAULT_TEXT = "<LOG>\n\n"; class Log { public: Log() : _logs(0), _log(LOG_DEFAULT_TEXT) {}; void add(const char *str, bool nl=true); void
#pragma once
#include <string>
extern const char* LOG_DEFAULT_TEXT = "<LOG>\n\n";
class Log
{
public:
Log() : _logs(0), _log(LOG_DEFAULT_TEXT) {};
void add(const char *str, bool nl=true);
void clear();
const char* get() const { return _log.c_str(); }
int getNumLogs() const { return _logs; }
private:
std::string _log;
int _logs;
};
//Main.h
...
#include "Log.h"
class Main() {
public:
...
private:
Log _log;
ImportantObject1(&_log); //pass a pointer to _log
ImportantObject2(&_log); //..same
};
这个解决方案似乎太笨拙了,所以我想问一下,对于我想要完成的事情,是否有不同的方法,即错误日志记录。这是一种罕见的单例有意义的情况之一:
class Log
{
public:
void add(const char *str, bool nl=true);
void clear();
const char* get() const { return _log.c_str(); }
int getNumLogs() const { return _logs; }
static Log& instance() {
static Log theInstance;
return theInstance;
}
private:
Log() : _logs(0), _log(LOG_DEFAULT_TEXT) {};
std::string _log;
int _logs;
};
这样,您就可以在其他地方使用它
Log::instance().add("Blah Blah",true);
另一种解决需求的方法 在合适的
命名空间中使用函数,而不是使用单例。
Log.h:
namespace Log
{
void add(const char *str, bool nl=true);
void clear();
const char* get();
int getNumLogs();
}
Log.cpp:
namespace detail
{
// This is almost same as the class from OP's post.
struct LogImpl
{
LogImpl(std::string const& log) : _logs(0), _log(log) {};
void add(const char *str, bool nl=true);
void clear();
const char* get() const { return _log.c_str(); }
int getNumLogs() const { return _logs; }
std::string _log;
int _logs;
};
}
namespace Log
{
// This mimics the singleton implementation...
// Create only one instance of LogImpl.
static detail::LogImpl impl("<LOG>\n\n");
void add(const char *str, bool nl)
{
impl.add(str, nl);
}
void clear()
{
impl.clear();
}
const char* get()
{
return impl.get();
}
int getNumLogs()
{
return impl.getNumLogs();
}
}
namespace Log
{
void add(const char *str, bool nl=true);
void clear();
const char* get();
int getNumLogs();
}
而不是
Log::instance()->add(...);
从C继承的另一个常见模式是全局对象。全球化通常是不受欢迎的,因为它们是糟糕设计的征兆。但作为一名全球记录者是有意义的 这意味着类的标题应包含:
extern Log log;
和人民党
#include <log.h>
...
Log log; // unique definition for the global Log
#包括
...
日志日志;//全局日志的唯一定义
然后在使用日志的任何模块中:
#include <log.h>
...
log.add(...);
#包括
...
log.add(…);
这里的警告是,将对日志进行静态初始化。和C++不总是很好的静态初始化顺序:否则,变量的初始化相对于变量的初始化是不确定的
在不同的转换单位中定义的变量。。唯一简单的方法是确保:
- 日志构造不依赖于任何其他静态初始化变量,该变量需要另一个翻译单元中的构造函数阶段-它包括
,但希望不是std::string
const char*
- 全局变量在任何多线程开始之前使用一次
如果有疑问,使用πάντα建议的单态模式ῥεῖ 如果需要更灵活的方法,这就是模式。@Quentin对于像日志记录这样的简单用例来说,这听起来有点过度设计了。如果您返回一个局部变量作为引用,它将无法正常工作;)事实上,我从来没有真正理解过单身汉背后的想法,现在我明白了。我总是被告知关于它们的可怕消息:P@πάνταῥεῖ 以防万一:)在使用globals时必须指出一点:如果全局对象的构造顺序没有很好地定义,您可能会遇到麻烦。可能创建了另一个全局对象并尝试记录,但记录器不可用,系统在没有日志的情况下崩溃;)但是,单例最终会出现在依赖树中,等等。没有模式是完美的。如果您知道自己在做什么,那么全局对象既便宜又快捷。但如果你不这样做,那就是噩梦的开始!
#include <log.h>
...
log.add(...);