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您始终可以使用仅静态的接口,因为所涉及的唯一数据可以通过静态方法访问。