avoiding enums as interface identifiers c++ OOP
- by AlasdairC
Hi
I'm working on a plugin framework using dynamic loaded shared libraries which is based on Eclipse's (and probally other's) extension-point model. All plugins share similar properties (name, id, version etc) and each plugin could in theory satisfy any extension-point. The actual plugin (ie Dll) handling is managed by another library, all I am doing really is managing collections of interfaces for the application.
I started by using an enum PluginType to distinguish the different interfaces, but I have quickly realised that using template functions made the code far cleaner and would leave the grunt work up to the compiler, rather than forcing me to use lots of switch {...} statements.
The only issue is where I need to specify like functionality for class members - most obvious example is the default plugin which provides a particular interface. A Settings class handles all settings, including the default plugin for an interface.
ie Skin newSkin = settings.GetDefault<ISkin>();
How do I store the default ISkin in a container without resorting to some other means of identifying the interface?
As I mentioned above, I currently use a std::map<PluginType, IPlugin> Settings::defaults member to achieve this (where IPlugin is an abstract base class which all plugins derive from. I can then dynamic_cast to the desired interface when required, but this really smells of bad design to me and introduces more harm than good I think.
would welcome any tips
edit: here's an example of the current use of default plugins
typedef boost::shared_ptr<ISkin> Skin;
typedef boost::shared_ptr<IPlugin> Plugin;
enum PluginType
{
skin,
...,
...
}
class Settings
{
public:
void SetDefault(const PluginType type, boost::shared_ptr<IPlugin> plugin) {
m_default[type] = plugin;
}
boost::shared_ptr<IPlugin> GetDefault(const PluginType type) {
return m_default[type];
}
private:
std::map<PluginType, boost::shared_ptr<IPlugin> m_default;
};
SkinManager::Initialize()
{
Plugin thedefault = g_settings.GetDefault(skinplugin);
Skin defaultskin = boost::dynamic_pointer_cast<ISkin>(theskin);
defaultskin->Initialize();
}
I would much rather call the getdefault as the following, with automatic casting to the derived class. However I need to specialize for every class type.
template<>
Skin Settings::GetDefault<ISkin>()
{
return boost::dynamic_pointer_cast<ISkin>(m_default(skin));
}