У меня есть иерархия классов, и каждый из них должен иметь определенный базовый класс. Чем базовый класс предоставляет возможность публиковать записи журнала и принимает имя ctor канала журнала (в основном имя класса, использующего журнал). Позволяет назвать этот класс Logable
.Устранение неоднозначности базового члена класса шаблона
Чтобы позволить моим классам наследовать от этого класса Logable
несколько раз, я дал ему параметр шаблона, и каждый потомок использует его как этот параметр.
На самом деле я использую библиотеку boost :: log, но есть очень упрощенный пример указанной иерархии с простым классом LogableImpl
, который заменяет boost :: log sink.
#include <iostream>
#include <string>
// macro for logging in a boost::log style
#define LOG_DEBUG this->_loggerObj.logStream("debug")
#define LOG_INFO this->_loggerObj.logStream("info")
#define LOG_WARN this->_loggerObj.logStream("warning")
#define LOG_ERROR this->_loggerObj.logStream("error")
class LogableImpl
{
private:
std::string _channelName;
public:
LogableImpl(const std::string & channelName): _channelName(channelName) {}
std::ostream & logStream(const std::string & severetyLevel)
{
std::cout << _channelName << " " << severetyLevel;
return std::cout;
}
};
template <class Descendant>
class Logable
{
protected:
Logable(const std::string & channelName): _loggerObj(channelName) {}
LogableImpl _loggerObj;
};
class Base: private Logable<Base>
{
public:
Base()
: Logable<Base>("Base")
{}
void someMethod()
{
LOG_INFO << "some method is called" << std::endl;
LOG_ERROR << "an error happened" << std::endl;
}
};
class Derived: public Base, private Logable<Derived>
{
public:
Derived()
: Logable<Derived>("Derived")
{}
void someAnotherMethod()
{
LOG_INFO << "another method is called" << std::endl;
LOG_ERROR << "another error is happened" << std::endl;
}
};
int main()
{
Base b;
Derived d;
b.someMethod();
d.someMethod();
return 0;
}
Очевидно, я получил сообщение об ошибке из моей компиляции попытки этого источника с MSVC 2008
error C2385: ambiguous access of '_loggerObj'
1> could be the '_loggerObj' in base 'Logable<Base>'
1> or could be the '_loggerObj' in base 'Logable<Derived>'
1>d:\cpp\visualstudio\tests\workbench\test\main.cpp(55) : error C2248: 'Logable<Descendant>::_loggerObj' : cannot access inaccessible member declared in class 'Logable<Descendant>'
1> with
1> [
1> Descendant=Base
1> ]
1> d:\cpp\visualstudio\tests\workbench\test\main.cpp(29) : see declaration of 'Logable<Descendant>::_loggerObj'
1> with
1> [
1> Descendant=Base
1> ]
1>d:\cpp\visualstudio\tests\workbench\test\main.cpp(56) : error C2385: ambiguous access of '_loggerObj'
1> could be the '_loggerObj' in base 'Logable<Base>'
1> or could be the '_loggerObj' in base 'Logable<Derived>'
1>d:\prog\cpp\visualstudio\tests\workbench\boost_test\main.cpp(56) : error C2248: 'Logable<Descendant>::_loggerObj' : cannot access inaccessible member declared in class 'Logable<Descendant>'
1> with
1> [
1> Descendant=Base
1> ]
1> d:\cpp\visualstudio\tests\workbench\test\main.cpp(29) : see declaration of 'Logable<Descendant>::_loggerObj'
1> with
1> [
1> Descendant=Base
1> ]
1>Build log was saved at "file://d:\cpp\visualStudio\tests\workbench\test\Debug\BuildLog.htm"
1>boost_test - 4 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Как я могу указать правильный элемент базы для использования в LOG_*
макросе? Я чувствую, что это можно сделать с помощью магии шаблонов, но просто не могу понять это.
Это должно быть сделано с msvc2008, который не поддерживает C++ 11x функции
Ну, какой '_loggerObj' вы хотите использовать в случае' Derived'? – Barry
@Barry - тот, который находится в прямом предписании 'Logable' –