我已经遇到很多时间,例如一个班级,例如LogFile
,没有默认构造函数,而我想初始化它的一个实例,而不是在堆上。
以下是一个例子:
LogFile logfile;
void init(const std::string& path) {
logfile = LogFile(path);
}
上面的代码无法编译,因为LogFile
类没有默认构造函数。
我目前使用了一些解决方法:
1。 坚持不要手动进行任何堆调用,将对象存储在列表中(列表肯定会使用堆,但我不会关心它)
std::list<LogFile> logfile_holder;
void init(const std::string& path) {
logfile_holder.push_back(LogFile(path));
}
2。 使用堆,使用共享指针/唯一指针:
std::shared_ptr<LogFile> logfile_ptr;
void init(const std::string& path) {
logfile_ptr.reset(new LogFile(path));
}
我有更标准的解决方案来做这些事情吗?
即使看起来像列表解决方法的东西,但是使用专门为此目的指定的模板类,没有列表的开销,也会很好。
答案 0 :(得分:5)
optional
可以替代(std
或boost
,具体取决于您的编译器版本):
std::optional<LogFile> logfile;
void init(const std::string& path) {
logfile = LogFile(path);
}
答案 1 :(得分:4)
您可以使用间接。使用全局指针,并使用函数local static:
初始化它LogFile* logfile_ptr;
void init(const std::string& path) {
static LogFile logfile(path);
logfile_ptr = &logfile;
}
对于您的建议,如果您要使用堆,则在使用智能指针时使用列表(或其他数据结构)没有什么意义。
请注意,在此基于您的设计中,您需要注意在初始化之前不要使用全局日志文件。如果不确定,很容易检查指针是否为空。
更简单的方法是简单地添加默认构造函数。如果在设置路径之前使用它,则允许更改Logfile
的行为。例如,您可以终止程序并描述错误,或者如果您不关心丢失的过早记录,您可以默默地忽略此类错误。或者您甚至可以将记录存储到缓冲区中,并在路径最终初始化后立即刷新它。
答案 2 :(得分:1)
通常的方法是将Logger
类分开并拥有一个Logfile
类,这些类在内部耦合并分别负责:
Logger
类在需要时实例化,用于编写文本格式的日志消息Logfile
类负责配置应用程序范围的日志文件。将有一个static
类成员代表与所有std::ostream
个实例共享的Logger
。这是草图:
class Logfile {
friend class Logger;
static std::unique_ptr<std::ostream> plogstream_;
public:
void set_logfile(const std::string& logfile_path) {
void set_logstream(std::unique_ptr<std::ostream> logstream);
};
Logfile::plogstream_ = std::unique_ptr<std::ostream>(std::cerr,[](void*){});
class Logger {
public:
operator ostream&()() {
return *Logfile::plogstream_;
}
};