避免在 C++ 中对一个实例调用多个函数成员
Avoid multiple function member call on an instance in C++
我为我的程序编写了一个记录器 class,但我想强制客户端以特定方式使用我的 class。这是我的 Logger
class:
#ifndef __LOGGER_HPP
#define __LOGGER_HPP
#include <Uncopyable.hpp>
#include <sstream>
enum LoggerLevel
{
ERROR,
WARNING,
INFO,
DEBUG,
ALL
};
class Logger : private Uncopyable
{
private:
static LoggerLevel reportingLevel;
static std::ostringstream os;
static bool hide;
static std::string file;
LoggerLevel messageLevel;
std::string className;
public:
static void setVerbosity(LoggerLevel level);
static void setLogFile(const std::string &file);
static void hideOutput();
static bool outputHidden();
static std::ostringstream &getStream();
Logger(const std::string &className);
~Logger();
std::ostringstream &debug();
std::ostringstream &info();
std::ostringstream &warning();
std::ostringstream &error();
};
#endif // __LOGGER_HPP
实施:
#include <Logger.hpp>
#include <iostream>
#include <fstream>
#include <cstdio>
#include <ctime>
using namespace std;
LoggerLevel Logger::reportingLevel = LoggerLevel::ALL;
ostringstream Logger::os;
string Logger::file;
bool Logger::hide = false;
Logger::Logger(const string &className) :
className(className)
{
os.str("");
}
Logger::~Logger()
{
os << endl;
if (this->messageLevel <= reportingLevel)
{
if (!hide)
{
if (this->messageLevel == LoggerLevel::ERROR)
{
cerr << os.str() << flush;
}
else
{
cout << os.str() << flush;
}
}
if (!file.empty())
{
time_t now = time(nullptr);
string time(ctime(&now));
ofstream log(file, ios::in | ios::app);
log << time.substr(0, time.length() - 1) << " " << os.str() << flush;
log.close();
}
}
}
void Logger::setVerbosity(LoggerLevel level)
{
Logger::reportingLevel = level;
}
void Logger::setLogFile(const string &file)
{
Logger::file = file;
}
void Logger::hideOutput()
{
Logger::hide = true;
}
bool Logger::outputHidden()
{
return hide;
}
ostringstream &Logger::getStream()
{
return os;
}
ostringstream &Logger::debug()
{
os << "[DEBUG] " << this->className << ": ";
this->messageLevel = LoggerLevel::DEBUG;
return os;
}
ostringstream &Logger::info()
{
os << "[INFO] " << this->className << ": ";
this->messageLevel = LoggerLevel::INFO;
return os;
}
ostringstream &Logger::warning()
{
os << "[WARNING] " << this->className << ": ";
this->messageLevel = LoggerLevel::WARNING;
return os;
}
ostringstream &Logger::error()
{
os << "[ERROR] " << this->className << ": ";
this->messageLevel = LoggerLevel::ERROR;
return os;
}
如您所见,我想强制客户端像这样使用 class:
Logger("MyCLass").debug() << "This is a debug message.";
所以我想静态地避免这种使用:
Logger myLogger("MyClass");
myLogger.debug() << "This is a debug message.";
myLogger.info() << "This is an information.";
有什么解决办法吗?
谢谢。
是的,有一个解决方案,感谢 C++11。您想要对每个日志记录函数进行右值引用限定:
std::ostringstream &debug() &&;
// etc.
换句话说,函数声明末尾的 &&
意味着 debug()
和朋友只能在临时 Logger
对象上调用:
Logger("MyClass").debug() << "foo"; // fine
Logger log("MyClass");
log.debug() << "bar"; // compile-time error!
我为我的程序编写了一个记录器 class,但我想强制客户端以特定方式使用我的 class。这是我的 Logger
class:
#ifndef __LOGGER_HPP
#define __LOGGER_HPP
#include <Uncopyable.hpp>
#include <sstream>
enum LoggerLevel
{
ERROR,
WARNING,
INFO,
DEBUG,
ALL
};
class Logger : private Uncopyable
{
private:
static LoggerLevel reportingLevel;
static std::ostringstream os;
static bool hide;
static std::string file;
LoggerLevel messageLevel;
std::string className;
public:
static void setVerbosity(LoggerLevel level);
static void setLogFile(const std::string &file);
static void hideOutput();
static bool outputHidden();
static std::ostringstream &getStream();
Logger(const std::string &className);
~Logger();
std::ostringstream &debug();
std::ostringstream &info();
std::ostringstream &warning();
std::ostringstream &error();
};
#endif // __LOGGER_HPP
实施:
#include <Logger.hpp>
#include <iostream>
#include <fstream>
#include <cstdio>
#include <ctime>
using namespace std;
LoggerLevel Logger::reportingLevel = LoggerLevel::ALL;
ostringstream Logger::os;
string Logger::file;
bool Logger::hide = false;
Logger::Logger(const string &className) :
className(className)
{
os.str("");
}
Logger::~Logger()
{
os << endl;
if (this->messageLevel <= reportingLevel)
{
if (!hide)
{
if (this->messageLevel == LoggerLevel::ERROR)
{
cerr << os.str() << flush;
}
else
{
cout << os.str() << flush;
}
}
if (!file.empty())
{
time_t now = time(nullptr);
string time(ctime(&now));
ofstream log(file, ios::in | ios::app);
log << time.substr(0, time.length() - 1) << " " << os.str() << flush;
log.close();
}
}
}
void Logger::setVerbosity(LoggerLevel level)
{
Logger::reportingLevel = level;
}
void Logger::setLogFile(const string &file)
{
Logger::file = file;
}
void Logger::hideOutput()
{
Logger::hide = true;
}
bool Logger::outputHidden()
{
return hide;
}
ostringstream &Logger::getStream()
{
return os;
}
ostringstream &Logger::debug()
{
os << "[DEBUG] " << this->className << ": ";
this->messageLevel = LoggerLevel::DEBUG;
return os;
}
ostringstream &Logger::info()
{
os << "[INFO] " << this->className << ": ";
this->messageLevel = LoggerLevel::INFO;
return os;
}
ostringstream &Logger::warning()
{
os << "[WARNING] " << this->className << ": ";
this->messageLevel = LoggerLevel::WARNING;
return os;
}
ostringstream &Logger::error()
{
os << "[ERROR] " << this->className << ": ";
this->messageLevel = LoggerLevel::ERROR;
return os;
}
如您所见,我想强制客户端像这样使用 class:
Logger("MyCLass").debug() << "This is a debug message.";
所以我想静态地避免这种使用:
Logger myLogger("MyClass");
myLogger.debug() << "This is a debug message.";
myLogger.info() << "This is an information.";
有什么解决办法吗? 谢谢。
是的,有一个解决方案,感谢 C++11。您想要对每个日志记录函数进行右值引用限定:
std::ostringstream &debug() &&;
// etc.
换句话说,函数声明末尾的 &&
意味着 debug()
和朋友只能在临时 Logger
对象上调用:
Logger("MyClass").debug() << "foo"; // fine
Logger log("MyClass");
log.debug() << "bar"; // compile-time error!