我认为更适合这个的是composition。与其尝试在基类 (ManagerBase) 中定义变量行为,不如让 Manager 定义行为应该发生的时间,并将该行为作为自己的对象传递给 Manager。不再需要 ManagerBase。
// *** Behaviour interfaces ***
// ILogger.h
class ILogger
{
public:
~ILogger(){};
virtual void Log( const char *pMessage ) = 0;
};
//*******************************
// IDatabse.h
class IDatabase
{
public:
~IDatabase(){}
virtual void CreateDB( const char *pDBName ) = 0;
};
//*******************************
// ** Manager **
// Manager.h
class ILogger;
class IDatabase;
class CManager
{
public:
CManager(
ILogger &logger,
IDatabase &db );
void Initialise( const char *pDBName );
private:
ILogger &m_logger;
IDatabase &m_db;
};
// Manager.cpp
#include "ILogger.h"
#include "IDatabase.h"
#include "Manager.h"
CManager::CManager( ILogger &logger, IDatabase &db )
: m_logger(logger) // this is like registering a Log callback
, m_db(db) // and a (set of) db callback/s
{
}
void CManager::Initialise( const char *pDBName )
{
m_logger.Log( "Initialising" ); // this is akin to raising a log 'event'
m_db.CreateDB( pDBName ); // and a create DB event.
}
//*******************************
// ** Application **
// Application.h
#include "ILogger.h"
#include "IDatabase.h"
#include "Manager.h"
class CApp : public ILogger, public IDatabase
{
/* You don't have to have your main app inherit the interface. You could
implement them as their own objects, owned by CApp, or at least
something that is reachable when contructing CManager */
public:
CApp()
: m_Manager( *this, *this )
{
m_Manager.Initialise("MyAwesomeDatabaseOfDoom");
}
// implement overrides for Log and CreateDB here.
void Log( const char* pMessage ){}
void CreateDB( const char *pDBName ){}
private:
CManager m_Manager;
};
//*******************************
// ** Application **
// main.cpp
int main()
{
CApp();
return 0;
};
这只是一个快速的模拟,所以如果它没有编译,请道歉。我希望它至少说明了这个想法。
如果您希望能够在运行时更改您的行为,您可以使用 ILogger/IDatabase 成员指针而不是 CManager 中的引用,并公开设置器以便您可以设置任何您喜欢的行为定义对象。这使您可以做一些有趣的事情,例如,通过实现 ILogger 的 CFileLogger 和 CDatabaseLogger 版本并适当地设置它们,根据配置文件设置更改您记录的内容。