RTTI can be incredibly useful for implementing a flexible plugin system. Here's how you might approach this:
First, define a base Plugin
interface:
#include <string>
class Plugin {
public:
virtual ~Plugin() = default;
virtual std::string GetName() const = 0;
virtual void Execute() = 0;
};
Next, create a PluginManager
class that can load and manage plugins:
#include <iostream>
#include <memory>
#include <typeinfo>
#include <vector>
class Plugin {/*...*/};
class PluginManager {
public:
void LoadPlugin(std::unique_ptr<Plugin> plugin) {
plugins_.push_back(std::move(plugin));
}
void ExecutePlugin(const std::string& name) {
for (const auto& plugin : plugins_) {
if (plugin->GetName() == name) {
std::cout << "Executing plugin: "
<< name << "\n";
plugin->Execute();
return;
}
}
std::cout << "Plugin not found: "
<< name << "\n";
}
void ListPlugins() {
for (const auto& plugin : plugins_) {
std::cout << "Plugin: " << plugin->GetName()
<< ", Type: " << typeid(*plugin).name()
<< "\n";
}
}
using PluginCollection =
std::vector<std::unique_ptr<Plugin>>;
const PluginCollection& GetPlugins() const {
return plugins_;
}
private:
PluginCollection plugins_;
};
Now, let's see how RTTI can be used within this system:
#include <iostream>
#include <memory>
#include <typeinfo>
#include <vector>
class Plugin {/*...*/};
class PluginManager {/*...*/};
class AudioPlugin : public Plugin {
public:
std::string GetName() const override {
return "AudioPlugin";
}
void Execute() override {
std::cout << "Playing audio\n";
}
};
class VideoPlugin : public Plugin {
public:
std::string GetName() const override {
return "VideoPlugin";
}
void Execute() override {
std::cout << "Playing video\n";
}
};
int main() {
PluginManager manager;
manager.LoadPlugin(
std::make_unique<AudioPlugin>());
manager.LoadPlugin(
std::make_unique<VideoPlugin>());
manager.ListPlugins();
// Using RTTI to check plugin types
for (const auto& plugin : manager.GetPlugins()) {
if (typeid(*plugin) == typeid(AudioPlugin)) {
std::cout << "Found an AudioPlugin\n";
} else if (typeid(*plugin) == typeid(VideoPlugin)) {
std::cout << "Found a VideoPlugin\n";
}
}
manager.ExecutePlugin("AudioPlugin");
manager.ExecutePlugin("VideoPlugin");
}
Plugin: AudioPlugin, Type: class AudioPlugin
Plugin: VideoPlugin, Type: class VideoPlugin
Found an AudioPlugin
Found a VideoPlugin
Executing plugin: AudioPlugin
Playing audio
Executing plugin: VideoPlugin
Playing video
In this example, RTTI allows us to identify the specific types of plugins at runtime. This can be particularly useful if you need to perform type-specific operations or if you're implementing a more complex plugin architecture.
Remember that while RTTI is powerful, it should be used judiciously. In many cases, virtual functions and polymorphism can provide similar functionality with better performance. However, for a plugin system where flexibility is key, RTTI can be a valuable tool.
Answers to questions are automatically generated and may not have been reviewed.
typeid()
Learn to identify and react to object types at runtime using RTTI, dynamic casting and the typeid()
operator