C++ 这个预处理器指令在这里可以接受吗?
拥有一个单例C++ 这个预处理器指令在这里可以接受吗?,c++,preprocessor-directive,C++,Preprocessor Directive,拥有一个单例Logger类,我想每次调用print方法时都编写Logger::GetInstance()。我能想到的唯一解决办法是#define。在这种情况下,有没有更好的方法,或者这个宏是合理的 #include <iostream> #include <fstream> class Logger { public: static Logger& GetInstance(); ~Logger(); template <typen
Logger
类,我想每次调用print方法时都编写Logger::GetInstance()
。我能想到的唯一解决办法是#define
。在这种情况下,有没有更好的方法,或者这个宏是合理的
#include <iostream>
#include <fstream>
class Logger
{
public:
static Logger& GetInstance();
~Logger();
template <typename T>
void Print(const T &t);
void SetNewline(bool b);
void SetLogging(bool b);
private:
Logger();
Logger(const Logger&);
void operator=(const Logger&);
bool newline;
bool log;
std::ofstream file;
};
int main()
{
#define logger Logger::GetInstance()
logger.Print("Hello");
//Logger::GetInstance().Print("Hello");
}
#包括
#包括
类记录器
{
公众:
静态记录器&GetInstance();
~Logger();
模板
无效打印(常量T&T);
无效设置换行符(布尔b);
无效设置记录(bool b);
私人:
记录器();
记录器(常数记录器&);
void运算符=(常量记录器&);
布尔新线;
布尔日志;
流文件的std::of;
};
int main()
{
#定义日志记录器::GetInstance()
logger.Print(“你好”);
//Logger::GetInstance().Print(“Hello”);
}
注意,由于您显然是在“本地”定义宏,宏不尊重作用域
为什么不定义函数而不是宏:
inline
auto logger() -> Logger& { return Logger::GetInstance(); }
那你就可以直接写了
logger().Print( "Hello" );
喝彩和hth的两种选择阿尔夫的回答是: 如果在一个范围内多次需要记录器,则可以为其指定一个名称:
Logger& logger = Logger::GetInstance();
// ...
logger.Print("Hello, world");
或者,您也可以将日志记录方法设置为静态:
static void Logger::Print(const T &t) {
Logger::GetInstance().Print(t);
}
然后静态地调用它们:
Logger::Print("Hello world!");
您可能会争辩说,对于客户端来说,是否确实存在实例并不重要——构造函数是私有的,因此他们无论如何都不能创建自己的实例。因此,静态方法是否创建实例不应该是他们关心的问题。在本例中,使用名为
GetInstance
的公共方法实际上会暴露不相关的实现细节 为什么在main
方法中定义记录器<代码>#定义不尊重范围。如果您只想在那里使用记录器
,也可以使用logger&logger=logger::GetInstance()
。让每个需要记录的对象都记录下来,在构造函数中调用GetInstance(),并存储引用?有点偏离主题,但我更愿意将记录器
作为参数传递给任何需要记录的函数。创建记录器的单点将是主要功能。我不喜欢全球可用的可修改状态。@我会考虑的。这只是我编造练习的游乐场,我还不是系统设计师,这是有原因的…:)如果您使记录器
类成为一个接口(即抽象)并作为引用/(智能)指针传递,您可以轻松地模拟记录器进行单元测试等。您也不会有生命周期问题(试想一种情况,另一个静态单例比记录器寿命长,但想要记录一些东西…+1,但为什么后面的返回类型?我不认为它在这里起作用。我使用它作为一个单一和统一的函数声明语法。为什么要使用多个语法?嗯,是的,更好,但仍然是函数调用语法。是的,我知道宏没有尊重范围,我只是把它放在那里让问题变得清晰。@angew同意。如果不需要类型推断,那完全没有必要。静态打印方法是迄今为止提出的所有方法中最好的一种。哇。我甚至没有想到存储引用,我立即想,好吧,这里不能有作业。那就很清楚了谢谢你。@Onur是的,当我在想这个问题时,有没有任何情况,你有一个单例类,但是你不能让它的方法是静态的?如果你愿意首先创建一个单例类,我不明白为什么它不能有一个静态接口。[..]此注释的其余部分变得有点长,因此我将其添加到了答案中。@Inkeeper您始终可以使用仅静态的接口,因为所涉及的唯一数据可以通过静态方法访问。