我试图实现具有3个级别的信息的记录器:一般(日期/时间),上下文,消息C++图案:1x基站类+ NX派生类但具有_Last resort_派生类
为了达到这个目标我想implemnet以下模式:
- Logger类(非此相关)
- Context类
- 基类
LoggerContext
,这有根的功能erating一般水平的相关信息 - 派生类,添加上下文中的具体的相关信息(具体为应用程序的一部分)
- 基类
有趣的部分开始,我尝试有一个没有上下文。也就是说,如果记录器没有上下文被调用,那么应该使用单例LoggerContextNone
。
这里我的代码,不管我怎么打开它,不编译:
#include <string>
#include <iostream>
#include <stdexcept>
using namespace std;
enum class LoggerArea {
LOGGER_NONE, LOGGER_DOWNLOAD, LOGGER_COMPUTE,
};
class ELoggerContext: std::runtime_error {
using std::runtime_error::runtime_error;
};
class LoggerContextNone; // forward declaration, only needed for
// the commented version of the code
class LoggerContext {
protected:
LoggerArea mLA;
public:
LoggerContext(LoggerArea la);
virtual ~LoggerContext() = 0;
/*
static LoggerContext& getEmptyContext() {
static LoggerContextNone loggerContextNone = { LoggerArea::LOGGER_NONE };
return loggerContextNone;
}
*/
std::string getGeneral();
virtual std::string getContext() = 0; // pure virtual
};
string LoggerContext::getGeneral() {
return "general informations";
}
LoggerContext::LoggerContext(LoggerArea la) :
mLA(la) {
if (la == LoggerArea::LOGGER_NONE) {
throw ELoggerContext("LOGGER_NONE cannot be instantiated");
}
}
class LoggerContextNone : LoggerContext {
private:
LoggerContextNone() {
mLA = LoggerArea::LOGGER_NONE;
}
public:
virtual ~LoggerContextNone() override {
}
virtual std::string getContext() override {
return " ";
}
static LoggerContextNone& getInstance() {
static LoggerContextNone instance {};
return instance;
}
};
int main() {
// this should not be compilable:
LoggerContextNone n{LoggerArea::LOGGER_NONE};
// this should at least throw an error at run time:
LoggerContext n{LoggerArea::LOGGER_NONE};
return 0;
}
目标:
LoggerContextNone
应该LoggerContext
派生,因为我们需要getGeneral()
LoggerContextNone
应不可实例化getInstance(单例)- 基类肩d有没有空的构造函数,但派生类应该有一个
LoggerContextNone
不应该调用超构造函数,否则会抛出一个错误ELoggerContext
- 从
LoggerContext
任何派生类不应该能够覆盖getGeneral()
实际上是否可以在C++中实现这一点?我正在寻找一个干净的解决方案(没有工厂,...)
编译器的错误是:
19_virtual_class.cpp: In constructor ‘LoggerContextNone::LoggerContextNone()’:
19_virtual_class.cpp:45:22: error: no matching function for call to ‘LoggerContext::LoggerContext()’
LoggerContextNone() {
^
[...]
19_virtual_class.cpp: In function ‘int main()’:
19_virtual_class.cpp:62:46: error: no matching function for call to ‘LoggerContextNone::LoggerContextNone(<brace-enclosed initializer list>)’
LoggerContextNone n{LoggerArea::LOGGER_NONE};
^
最后说明一点:这个模式似乎我的概念是很简单:从一个基类派生许多类的另外还有一个默认类。
编辑:
如果我调整代码由@Angew:
#include <string>
#include <iostream>
#include <stdexcept>
using namespace std;
enum class LoggerArea {
LOGGER_NONE, LOGGER_DOWNLOAD, LOGGER_COMPUTE,
};
class ELoggerContext: std::runtime_error {
using std::runtime_error::runtime_error;
};
class LoggerContextNone;
class LoggerContext {
protected:
LoggerArea mLA;
class LoggerContextNone_AccessToken
{
friend LoggerContextNone;
LoggerContextNone_AccessToken() {}
};
explicit LoggerContext(LoggerContextNone_AccessToken) : mLA(LoggerArea::LOGGER_NONE) {}
public:
LoggerContext(LoggerArea la);
virtual ~LoggerContext() = 0;
std::string getGeneral();
virtual std::string getContext() = 0;
};
string LoggerContext::getGeneral() {
string s = "general informations:";
if (mLA==LoggerArea::LOGGER_NONE) { s += "LOGGER_NONE"; }
else if (mLA==LoggerArea::LOGGER_DOWNLOAD) { s += "LOGGER_DOWNLOAD"; }
else if (mLA==LoggerArea::LOGGER_COMPUTE) { s += "LOGGER_COMPUTE"; }
else { s += "??????????"; }
return s;
}
LoggerContext::LoggerContext(LoggerArea la) :
mLA(la) {
if (la == LoggerArea::LOGGER_NONE) {
throw ELoggerContext("LOGGER_NONE cannot be instantiated");
}
}
class LoggerContextNone : LoggerContext {
private:
LoggerContextNone(): LoggerContext(LoggerContextNone_AccessToken()) {}
public:
virtual ~LoggerContextNone() override {
}
virtual std::string getContext() override {
return " ";
}
static LoggerContextNone& getInstance() {
static LoggerContextNone instance {};
return instance;
}
};
class LoggerContextDerived : LoggerContext {
public:
virtual std::string getContext() override {
return "derived context";
}
};
int main() {
LoggerContextDerived n {LoggerArea::LOGGER_DOWNLOAD};
// cout << "General : " << n.getGeneral() << endl;
// cout << "Context : " << n.getContext() << endl;
return 0;
}
我不能实例派生类。 g++
说:
9_virtual_class.cpp: In function ‘int main()’:
19_virtual_class.cpp:78:54: error: no matching function for call to ‘LoggerContextDerived::LoggerContextDerived(<brace-enclosed initializer list>)’
LoggerContextDerived n {LoggerArea::LOGGER_DOWNLOAD};
^
而且它建议我使用复制构造函数或移动构造函数。 对我意味着什么,构造
LoggerContext(LoggerArea la);
是不是在派生类中可见。
感谢您长期以来的答复,但它接缝要有些东西仍然不适用于构造函数,请参阅我对该问题的编辑。 – LiPo
@LiPo这是一个相互无关的问题。您不能使用基类ctor构造C++中的派生类。如果你想在派生类中使用单参数,你需要在那里定义这样的一个ctor。或者使用构造函数继承('使用LoggerContext :: LoggerContext'),但那会继承*所有*构造函数。 – Angew
@LiPo您可能想了解更多关于C++构造函数如何在[好书](http://stackoverflow.com/q/388242/1782465)中工作的内容。 – Angew