我正在尝试创建一个记录到std :: cout和文件的记录器。这是我的班级:
.h文件:
class ProblemsManager {
(...)
private:
(...)
class logger {
private:
std::ofstream fileStream;
static const std::string LOG_PATH;
public:
logger();
~logger();
template<class T>
friend logger & operator<<(logger &log, const T & bytes) {
log.fileStream<<bytes;
std::cout<<bytes;
return log;
}
};
};
.cpp文件
(...)
const std::string ProblemsManager::logger::LOG_PATH = "F:\\Dropbox\\workspace - Visual Studio\\PEuler\\PEuler\\PEuler.log";
ProblemsManager::logger::logger() : fileStream(LOG_PATH,std::ofstream::out) {}
ProblemsManager::logger::~logger() {}
然后,如果我尝试:
ProblemsManager::logger log;
log<<"test";
我明白了:
1&gt; f:\ dropbox \ workspace - visual studio \ peuler \ peuler \ problemsmanager.cpp(47):错误C3767:'&lt;&lt;':候选函数无法访问 1 GT;可能是'f:\ dropbox \ workspace中的朋友函数 - visual studio \ peuler \ peuler \ problemsmanager.h(37)':'&lt;&lt;' [可以通过参数依赖查找找到]
答案 0 :(得分:3)
您的模板存在一些问题,第一个问题是两者仅在引用方面存在差异,这会导致问题。你只需要一个(读取和不写入参数):
template<class T>
friend logger & operator<<(logger& log, const T & bytes);
// ^^^^^
现在第二个问题是应该在生成实例化时编译器可以看到的位置定义模板。这基本上意味着定义必须在标题中,而不是在.cpp文件中。 [*]
除此之外,由于logger
类型对ProblemsManager
是私有的,因此您无法从命名空间级别访问它,因此您将无法定义自由函数,因为它无法访问嵌套类型。选项是将类型设为public,使该函数也成为ProblemsManager
的朋友,或者正如我所建议的那样,只需在类定义中内联定义模板:
class ProblemsManager {
private:
class logger {
template<class T>
friend logger & operator<<(logger& log, T & bytes) {
// implementation goes here
}
};
};
[*] 这可能实际上是规则的例外,因为作为私有类型,我只能假设所有使用logger
,因此{{1}将在定义operator<<
成员的翻译单元内发生。如果是这种情况,您可以忽略这一段。
答案 1 :(得分:0)
作为运算符&lt;&lt;函数不是成员,而是朋友,你不能在其中使用'this'。您可能希望在那里返回'log',并使用'log。'来适当地限定日志成员。
答案 2 :(得分:0)
我会给它一个远景。
log<<"test";
以上呼叫是对运营商的呼叫&lt;&lt;函数与logger&amp;的第一个参数还有第二个const char [5]。
第一个重载可能无法绑定,因为您在引用和传递const对象上重载。第二个失败,因为你按值传递数组,你不能这样做。我只是不确定为什么你的数组没有折叠到指针。
您是否尝试过重引用const引用?顺便说一下 - 为什么你在价值和参考上超载?