给出以下工作代码。
#include <iostream>
template<class Detail>
class AbstractLogger
{
public:
static void log(const char* str) {
Detail::log_detailled(str);
}
};
class Logger : public AbstractLogger<Logger>
{
public:
static void log_detailled(const char* str) {
std::cerr << str << std::endl;
}
};
int main(void)
{
AbstractLogger<Logger>::log("main function running!");
return 0;
}
现在,我想输入 AbstractLogger
到一个库中,并让库用户定义自己的记录器,例如 Logger
在这里上课。这有一个缺点:AbstractLogger<Logger>
不能在库内部使用,因为库无法知道 Logger
.
注释:
- 请不要使用虚拟函数或提出为什么不这样做的问题。另外,我知道“静态虚拟”成员无效的类似问题。也许 CRTP 中有一个解决方法:)
- C++11 会很有趣,但是,我需要“普通”C++。
最佳答案
如果您的意思是您想要一个在不知道确切实例化类型的情况下使用它作为日志记录机制的库,我建议您不要这样做。
在满足其他要求(即无虚拟函数)的同时,唯一的方法是将库中需要记录的所有函数/类型转换为采用 Logger
类型的模板。最终结果是,您的大部分界面变成了模板(尽管您可能可以将大量实现转移到非模板化代码,但这将使您的生活比需要的困难得多,并且仍然会生成更大的二进制文件) .
如果您对虚拟函数的关注是性能,那么您应该重新考虑您的方法及其带来的问题。特别是,日志记录成本昂贵。大多数日志记录库通过优化非日志记录情况来解决这个问题(通过宏,如果日志级别/组/...未启用,则避免调用记录器),但仍然为实际写入保留动态调度。与写入控制台或文件的成本,甚至与生成将记录的消息的成本相比,动态调度的成本可以忽略不计(我假设您不仅记录文字字符串)
关于c++ - 静态 CRTP 类不知道派生类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12866070/