Accessing sub class's member functions through base class pointer - c++

I am trying to write a class that uses DOM to write a list of Registrations to file as XML. The list of registrations contains three types of registration Registration which is the standard base registration class GuestRegistration and StudentRegistration which both derive from Registration.
The GuestRegistration class has a unique member category and the student registration has unique member qualification.
When I iterate over the list of registration pointers I only have access to the base class Registration's member functions. Is there any way I can access the subclasses' data members to use the getter functions getCategory and getQualification? I've tried creating a GuestRegistration and StudentRegistration pointer whenever the class name matches either of the two, but get a pointer conversion error.
void RegistrationListWriter::write(RegistrationList r) {
QList<Registration*> regList = r.getRegistrationList();
for (int i = 0; i < regList.size(); ++i) {
QString cn = regList.at(i)->metaObject()->className();
Person tempPerson = regList.at(i)->getAttendee();
appendRegistrationAndType(cn);
appendAttendee(tempPerson);
//this is where my issue starts
if (cn == "GuestRegistration") {
GuestRegistration guestReg = regList.at(i);
appendAttendeeCatagory(guestReg.getCatagory());
}
if (cn == "StudentRegistration") {
StudentRegistration* stuReg = regList.at(i);
appendAttendeeQualification(stuReg->getQualification());
}
appendBookingDate(regList.at(i)->getBookingDate().toString());
appendRegistrationFee(regList.at(i)->calculateFee());
}
}

You can use dynamic_cast to check for specific sub-classes:
void RegistrationListWriter::write(RegistrationList r) {
QList<Registration*> regList = r.getRegistrationList();
for (int i = 0; i < regList.size(); ++i) {
Registration *reg = regList.at(i);
appendRegistrationAndType(reg->metaObject()->className());
appendAttendee(reg->getAttendee());
if (GuestRegistration *guestReg = dynamic_cast<GuestRegistration*>(reg)) {
appendAttendeeCatagory(guestReg->getCatagory());
}
else
if (StudentRegistration* stuReg = dynamic_cast<StudentRegistration*>(reg)) {
appendAttendeeQualification(stuReg->getQualification());
}
// and so on ...
appendBookingDate(reg->getBookingDate().toString());
appendRegistrationFee(reg->calculateFee());
}
}
However, I would suggest implementing a virtual method in the Registration class itself that your sub-classes can override to register additional items as needed, eg:
class Registration {
...
virtual void appendExtraAttendees(RegistrationListWriter *writer){}
...
};
class GuestRegistration : public Registration {
...
virtual void appendExtraAttendees(RegistrationListWriter *writer);
...
};
void GuestRegistration::appendExtraAttendees(RegistrationListWriter *writer){
writer->appendAttendeeCatagory(getCatagory());
}
class StudentRegistration : public Registration {
...
virtual void appendExtraAttendees(RegistrationListWriter *writer);
...
};
void StudentRegistration::appendExtraAttendees(RegistrationListWriter *writer){
writer->appendAttendeeQualification(getQualification());
}
void RegistrationListWriter::write(RegistrationList r) {
QList<Registration*> regList = r.getRegistrationList();
for (int i = 0; i < regList.size(); ++i) {
Registration *reg = regList.at(i);
appendRegistrationAndType(reg->metaObject()->className());
appendAttendee(reg->getAttendee());
reg->appendExtraAttendees(this);
appendBookingDate(reg->getBookingDate().toString());
appendRegistrationFee(reg->calculateFee());
}
}
Alternatively:
class Registration {
...
virtual void appendAttendees(RegistrationListWriter *writer);
...
};
void Registration::appendAttendees(RegistrationListWriter *writer){
writer->appendAttendee(getAttendee());
}
class GuestRegistration : public Registration {
...
virtual void appendAttendees(RegistrationListWriter *writer);
...
};
void GuestRegistration::appendAttendees(RegistrationListWriter *writer){
Registration::appendAttendees(writer);
writer->appendAttendeeCatagory(getCatagory());
}
class StudentRegistration : public Registration {
...
virtual void appendAttendees(RegistrationListWriter *writer);
...
};
void StudentRegistration::appendAttendees(RegistrationListWriter *writer){
Registration::appendAttendees(writer);
writer->appendAttendeeQualification(getQualification());
}
void RegistrationListWriter::write(RegistrationList r) {
QList<Registration*> regList = r.getRegistrationList();
for (int i = 0; i < regList.size(); ++i) {
Registration *reg = regList.at(i);
appendRegistrationAndType(reg->metaObject()->className());
reg->appendAttendees(this);
appendBookingDate(reg->getBookingDate().toString());
appendRegistrationFee(reg->calculateFee());
}
}

The straightforward C++ tool is dynamic_cast<>().
In general it is not good practice to initially design a project that requires such cast. Various design pattern may be considered.
I see that you are using metaObject(), so it means that Registration has QObject as a base class. In that case it is possible to use qobject_cast:
The qobject_cast() function behaves similarly to the standard C++
dynamic_cast(), with the advantages that it doesn't require RTTI
support and it works across dynamic library boundaries.

Instead of using dynamic_cast, you could have the base class provide an interface that the derived classes use to write their class-specific data.

Probably you need to make the methods virtual.
Non virtual method use the methods of the class used at compile time, virtual methods of subclasses are chosen instead at runtime.

Related

C++ polymorphism: how to create derived class objects

I have an abstract base class called BaseStrategy. It contains one pure virtual function calculateEfficiency(). There are two classes ConvolutionStrategy and MaxPoolStrategy which derive from this base class and implement their own specific version of calculateEfficiency().
Here is some code:
class BaseStrategy {
public:
explicit BaseStrategy();
virtual ~BaseStrategy() = default;
private:
virtual double calculateEfficiency(mlir::Operation* op) = 0;
};
class ConvolutionStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for convolution
return 1;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
double calculateEfficiency(mlir::Operation* op)
{
//some formula for MaxPool
return 1;
}
};
Now I have another class called StrategyAssigner. It has method calculateAllLayerEfficiencies() whose purpose is to iterate over all layers in a network. Depending on the type of layer there is a switch statement and should call the correct calculateEfficiency() depending on the layer type.
class StrategyAssigner final {
public:
explicit StrategyAssigner(){};
public:
void calculateAllLayerEfficiencies() {
// Logic to iterate over all layers in
// a network
switch (layerType) {
case Convolution:
// Call calculateEfficiency() for Convolution
break;
case MaxPool:
// Call calculateEfficiency() for MaxPool
break;
}
};
}
int main ()
{
StrategyAssigner assigner;
assigner.calculateAllLayerEfficiencies();
}
My question is, should I store references of objects Convolution and MaxPool in the class StrategyAssigner so that I can call the respective calculateEfficiency().
Or could you suggest a better way to call calculateEfficiency(). I don't really know how to create the objects (stupid as that sounds).
I can't make calculateEfficiency() static as I need them to be virtual so that each derived class can implemented its own formula.
If you included complete code I could give a more detailed answer, but you need to store BaseStrategy pointers that are initialized with derived class instances. Here's an example made from some of your code:
std::vector<std::unique_ptr<BaseStrategy>> strategies;
strategies.emplace_back(new ConvolutionStrategy);
strategies.emplace_back(new MaxPoolStrategy);
for (int i = 0; i < strategies.size(); ++i) {
std::unique_ptr<BaseStrategy>& pStrat = strategies[i];
pStrat->calculateEfficiency(...);
}
Note that this won't compile because I don't have enough details from the code you posted to make it so, but this shows how to exploit polymorphism in the way that you need.
Also, I used smart pointers for memory management; use these at your discretion.
You can indeed use runtime polymorphism here:
Declare ~BaseStrategy virtual (you are already doing it ;-)
If you are never going to instantiate a BaseStrategy, declare one of its methods as virtual pure, e.g. calculateEfficiency (you are already doing it as well!). I would make that method const, since it doesn't look it's going to modify the instance. And it will need to be public, because it will need to be accessed from StrategyAnalyser.
Declare calculateEfficiency as virtual and override in each of the subclasses. It could also be final if you don't want subclasses to override it.
I'd keep a std::vector of smart pointers to BaseStrategy at StrategyAssigner. You can use unique_ptrs if you think this class is not going to be sharing those pointers.
The key point now is that you create heap instances of the subclasses and assign them to a pointer of the base class.
class StrategyAssigner final {
public:
void addStrategy(std::unique_ptr<BaseStrategy> s) {
strategies_.push_back(std::move(s));
}
private:
std::vector<std::unique_ptr<BaseStrategy>> strategies_{};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
}
Then, when you call calculateEfficiency using any of those pointers to BaseStrategy, the runtime polymorphism will kick in and it will be the method for the subclass the one that will be actually called.
class ConvolutionStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "ConvolutionStrategy::calculateEfficiency()\n";
return 10;
}
};
class MaxPoolStrategy : public BaseStrategy {
private:
virtual double calculateEfficiency() const override {
std::cout << "MaxPoolStrategy::calculateEfficiency()\n";
return 20;
}
};
class StrategyAssigner final {
public:
void calculateAllLayerEfficiencies() {
auto sum = std::accumulate(std::cbegin(strategies_), std::cend(strategies_), 0,
[](auto total, const auto& strategy_up) {
return total + strategy_up->calculateEfficiency(); });
std::cout << "Sum of all efficiencies: " << sum << "\n";
};
};
int main()
{
StrategyAssigner assigner;
assigner.addStrategy(std::make_unique<ConvolutionStrategy>());
assigner.addStrategy(std::make_unique<MaxPoolStrategy>());
assigner.calculateAllLayerEfficiencies();
}
// Outputs:
//
// ConvolutionStrategy::calculateEfficiency()
// MaxPoolStrategy::calculateEfficiency()
// Sum of all efficiencies: 30
[Demo]

How to add functionality from combination of different derived class?

I have multiple handlers derived from base Handler class which can do single data updates individually.
For eg.
class Handler {
public:
Data_t dbdata_;
public:
virtual void updateFlags() = 0;
}
class AHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagA = 1; }
}
class BHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagB = 1; }
}
class CHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagC = 1; }
}
Individual handlers are called based on input flags in request. If request contains multiple flags, then in this case I want to try to avoid creating additional 6 handlers individually like following.
class ACHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagA = 1; dbdata_.flagC = 1; }
}
class ABCHandler: public Handler {
.....
public:
void updateFlags() { dbdata_.flagA = 1; dbdata_.flagB = 1; dbdata_.flagC = 1 }
}
Main function code will be something similar to this.
void process(Request_t *request)
{
Handler *handler;
if (request->flagA)
handler = new AHandler();
else if (request->flagB)
handler = new BHandler();
....
...
handler->updateFlags();
}
Is there a better way to approach this problem, by re-writing how the handlers are connected to each other ?
Thanks in advance.
If this is all your classes do, then I dont think u need any other class then Handler. Just simply let the Handler handle all the flags. It will be easy and simple like that. I think you might be overthinking this. Get a working simple version and then review it and decide if u need to and can refractor it.
I dont know what type your Request_t->flag(x) and Data_t->flag(x) is.
But cant you just do
dbdata_.flagA = request_t.flagA;
dbdata_.flagB = request_t.flagB;
etc. If you can maybe make them an array instead of individual variables, for easier setting.
You may want to consider a policy-based class design. For this, we define both a variadic function template, execute(), and a class template, HandlerHolder, that inherits from Handler and overrides the updateFlags() member function:
template<typename FlagUpdater, typename... FlagUpdaters>
void execute(Data_t& data) {
execute<FlagUpdater>(data);
if constexpr (sizeof...(FlagUpdaters))
execute<FlagUpdaters...>(data);
}
template<typename... FlagUpdaters>
class HandlerHolder final: public Handler {
public:
void updateFlags() override {
if constexpr (sizeof...(FlagUpdaters))
execute<FlagUpdaters...>(dbdata_);
}
};
To this variadic class template, HandlerHolder, you can pass classes (i.e., policies) as template arguments that are callables and set the proper flags. The function call operator (i.e., operator()) of these policy classes are called in its overridden member function updateFlags().
You would then define the policy classes like:
struct AFlagSetter {
void operator()(Data_t& dbdata) const {
dbdata.flagA = 1;
}
};
struct BFlagSetter {
void operator()(Data_t& dbdata) const {
dbdata.flagB = 1;
}
};
struct CFlagSetter {
void operator()(Data_t& dbdata) const {
dbdata.flagC = 1;
}
};
Note that you can also easily define policies for clearing the flags, for example:
struct CFlagClearer {
void operator()(Data_t& dbdata) const {
dbdata.flagC = 0;
}
};
By means of type aliases you can introduce type names for the handlers you were looking for:
using ACHandler = HandlerHolder<AFlagSetter, BFlagSetter>;
using ABCHandler = HandlerHolder<AFlagSetter, BFlagSetter, CFlagSetter>;

Lookup a specific type from a list in C++ using templates not including base classes

This may be impossible so alternative solutions to the problem will suffice as well
I have a list of activities that I want to keep track of
class Activity {
public:
virtual void DoSomething() = 0 ;
};
std::vector<Activity*> activities;
Let's say I have the following child classes
class GraphicsActivity : public Activity {
public:
virtual void DoSomething() { }
void HandleGraphics() { /* do some management */; }
};
class UpdateActivity : public Activity {
public:
virtual void DoSomething() { ; }
};
class PhysicsActivity : public Activity {
public:
virtual void DoSomething() { ; }
};
Now let's say we want to grab one of these activities from our list. A function would look like
template<typename T> T* GetActivity() {
for(int i = 0; i < activities.size(); i++) {
T* cast = dynamic_cast<T*>(activities[i]);
if(cast != nullptr) {
return cast;
}
}
return nullptr;
}
We could use it like so:
activities.push_back(new GraphicsActivity());
activities.push_back(new PhysicsActivity ());
activities.push_back(new UpdateActivity ());
GraphicsActivity* g = GetActivity<GraphicsActivity>();
Let's say we have another activity that needs to use polymorphism to use some of the base class's methods.
class 3DGraphicsActivity : public GraphicsActivity {
public:
void Handle3DGraphics() {
/* Utilize base class function */
this->HandleGraphics();
/* do some extra work */
}
};
Now we want to acquire the same activity as before and our list now looks like the following in the exact order:
activities.push_back(new GraphicsActivity3D());
activities.push_back(new GraphicsActivity());
activities.push_back(new PhysicsActivity ());
activities.push_back(new UpdateActivity ());
But we want the original type of GraphicsActivity, so we go to acquire it:
GraphicsActivity* g = GetActivity<GraphicsActivity>();
We'll actually get a pointer to the first entry in the list because it shares a base class of type GraphicsActivity.
Herein lies the problem: how can I write such a list whose items must share the same base class Activity while also be able to acquire the exact type from the list without falling into the dynamic_cast trap we just explained?
The typeid operator can be used to check if a polymorphic object has a certain exact most-derived type.
#include <typeinfo>
// ...
template<typename T> T* GetActivity() {
for(int i = 0; i < activities.size(); i++) {
auto* act = activities[i];
if (act != nullptr && typeid(*act) == typeid(T)) {
return dynamic_cast<T*>(act);
}
}
return nullptr;
}
Use this pattern with caution, because it limits the ability to make a class which acts exactly like another class except for specific changes. But it might be appropriate in your interface.

Is there a better way to design this message passing code?

class A was using below two functions to build and send messages 1 & 2
builder::prepareAndDeliverMsg1(msg1_arg1,msg1_arg2)
{
}
builder::prepareAndDeliverMsg2(msg2_arg1,msg2_arg2)
{
}
Now, a new class B is introduced, which would like to do what A was doing in two stages
stage1->prepare
stage2->deliver
I was thinking to extend the builder class like below:
///----
builder::prepareMsg1(msg1_arg1,msg1_arg2)
{
}
builder::prepareMsg2(msg2_arg1,msg2_arg2)
{
}
builder::deliverMsg1(msg1_arg1)
{
This function, inserts re-calculated msg1_arg1 into the prepared message in stage1
}
builder::deliverMsg2(msg2_arg1)
{
This function, inserts re-calculated msg2_arg1 into the prepared message in stage1
}
// These two functions are still retained for the usage of class A
builder::prepareAndDeliverMsg1(msg1_arg1,msg1_arg2)
{
}
builder::prepareAndDeliverMsg2(msg2_arg1,msg2_arg2)
{
}
//---
I would like to know, if there is any better way of designing this ?
maybe for each message, create your own class and inherit from the base message class?
class TBaseMsg
{
public:
virtual void prepare() = 0;
virtual void deliver() = 0;
}
You can take a look at Decorator design pattern.
http://en.wikipedia.org/wiki/Decorator_pattern
To expand on Darks idea you can have a base class that implements the combined prepare and delivers in terms of the separate functions and allows deriving classes to override those as required:
class base {
virtual bool prepareMsg1() = 0;
virtual bool prepareMsg2() = 0;
virtual bool deliverMsg1() = 0;
virtual bool deliverMsg2() = 0;
bool prepareAndDeliverMsg1(){
prepareMsg1();
deliverMsg1();
}
bool prepareAndDeliverMsg2(msg2_arg1,msg2_arg2){
prepareMsg2();
deliverMsg2();
}
};
You may find that a lot of the functionality from the two derived classes is the same in which case you won't want to use pure virtuals in the base class:
class base {
virtual bool prepareMsg1(args) {//not pure virtual
//do the common stuff
}
};
class derived {
bool prepareMsg1( args ) {
base::prepareMsg1(args);
//code to specailise the message
}
};
It could even be that the base class implments your original class but allows your second class to be derived without having to repeat the common code.
Your solution looks ok to me.

How to design a simple C++ object factory?

In my application, there are 10-20 classes that are instantiated once[*]. Here's an example:
class SomeOtherManager;
class SomeManagerClass {
public:
SomeManagerClass(SomeOtherManager*);
virtual void someMethod1();
virtual void someMethod2();
};
Instances of the classes are contained in one object:
class TheManager {
public:
virtual SomeManagerClass* someManagerClass() const;
virtual SomeOtherManager* someOtherManager() const;
/** More objects... up to 10-20 */
};
Currently TheManager uses the new operator in order to create objects.
My intention is to be able to replace, using plugins, the SomeManagerClass (or any other class) implementation with another one. In order to replace the implementation, 2 steps are needed:
Define a class DerivedSomeManagerClass, which inherits SomeManagerClass [plugin]
Create the new class (DerivedSomeManagerClass) instead of the default (SomeManagerClass) [application]
I guess I need some kind of object factory, but it should be fairly simple since there's always only one type to create (the default implementation or the user implementation).
Any idea about how to design a simple factory like I just described? Consider the fact that there might be more classes in the future, so it should be easy to extend.
[*] I don't care if it happens more than once.
Edit: Please note that there are more than two objects that are contained in TheManager.
Assuming a class (plugin1) which inherits from SomeManagerClass, you need a class hierarchy to build your types:
class factory
{
public:
virtual SomeManagerClass* create() = 0;
};
class plugin1_factory : public factory
{
public:
SomeManagerClass* create() { return new plugin1(); }
};
Then you can assign those factories to a std::map, where they are bound to strings
std::map<string, factory*> factory_map;
...
factory_map["plugin1"] = new plugin1_factory();
Finally your TheManager just needs to know the name of the plugin (as string) and can return an object of type SomeManagerClass with just one line of code:
SomeManagerClass* obj = factory_map[plugin_name]->create();
EDIT: If you don't like to have one plugin factory class for each plugin, you could modify the previous pattern with this:
template <class plugin_type>
class plugin_factory : public factory
{
public:
SomeManagerClass* create() { return new plugin_type(); }
};
factory_map["plugin1"] = new plugin_factory<plugin1>();
I think this is a much better solution. Moreover the 'plugin_factory' class could add itself to the 'factory_map' if you pass costructor the string.
I think there are two separate problems here.
One problem is: how does TheManager name the class that it has to create? It must keep some kind of pointer to "a way to create the class". Possible solutions are:
keeping a separate pointer for each kind of class, with a way to set it, but you already said that you don't like this as it violates the DRY principle
keeping some sort of table where the key is an enum or a string; in this case the setter is a single function with parameters (of course if the key is an enum you can use a vector instead of a map)
The other problem is: what is this "way to create a class"? Unfortunately we can't store pointers to constructors directly, but we can:
create, as others have pointed out, a factory for each class
just add a static "create" function for each class; if they keep a consistent signature, you can just use their pointers to functions
Templates can help in avoiding unnecessary code duplication in both cases.
I have answered in another SO question about C++ factories. Please see there if a flexible factory is of interest. I try to describe an old way from ET++ to use macros which has worked great for me.
ET++ was a project to port old MacApp to C++ and X11. In the effort of it Eric Gamma etc started to think about Design Patterns
I'd create a "base" factory that has virtual methods for creation of all the basic managers, and let the "meta manager" (TheManager in your question) take a pointer to the base factory as a constructor parameter.
I'm assuming that the "factory" can customize the instances of CXYZWManager by deriving from them, but alternatively the constructor of CXYZWManager could take different arguments in the "custom" factory.
A lengthy code example that outputs "CSomeManager" and "CDerivedFromSomeManager":
#include <iostream>
//--------------------------------------------------------------------------------
class CSomeManager
{
public:
virtual const char * ShoutOut() { return "CSomeManager";}
};
//--------------------------------------------------------------------------------
class COtherManager
{
};
//--------------------------------------------------------------------------------
class TheManagerFactory
{
public:
// Non-static, non-const to allow polymorphism-abuse
virtual CSomeManager *CreateSomeManager() { return new CSomeManager(); }
virtual COtherManager *CreateOtherManager() { return new COtherManager(); }
};
//--------------------------------------------------------------------------------
class CDerivedFromSomeManager : public CSomeManager
{
public:
virtual const char * ShoutOut() { return "CDerivedFromSomeManager";}
};
//--------------------------------------------------------------------------------
class TheCustomManagerFactory : public TheManagerFactory
{
public:
virtual CDerivedFromSomeManager *CreateSomeManager() { return new CDerivedFromSomeManager(); }
};
//--------------------------------------------------------------------------------
class CMetaManager
{
public:
CMetaManager(TheManagerFactory *ip_factory)
: mp_some_manager(ip_factory->CreateSomeManager()),
mp_other_manager(ip_factory->CreateOtherManager())
{}
CSomeManager *GetSomeManager() { return mp_some_manager; }
COtherManager *GetOtherManager() { return mp_other_manager; }
private:
CSomeManager *mp_some_manager;
COtherManager *mp_other_manager;
};
//--------------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
TheManagerFactory standard_factory;
TheCustomManagerFactory custom_factory;
CMetaManager meta_manager_1(&standard_factory);
CMetaManager meta_manager_2(&custom_factory);
std::cout << meta_manager_1.GetSomeManager()->ShoutOut() << "\n";
std::cout << meta_manager_2.GetSomeManager()->ShoutOut() << "\n";
return 0;
}
Here's the solution I thought of, it's not the best one but maybe it will help to think of better solutions:
For each class there would be a creator class:
class SomeManagerClassCreator {
public:
virtual SomeManagerClass* create(SomeOtherManager* someOtherManager) {
return new SomeManagerClass(someOtherManager);
}
};
Then, the creators will be gathered in one class:
class SomeManagerClassCreator;
class SomeOtherManagerCreator;
class TheCreator {
public:
void setSomeManagerClassCreator(SomeManagerClassCreator*);
SomeManagerClassCreator* someManagerClassCreator() const;
void setSomeOtherManagerCreator(SomeOtherManagerCreator*);
SomeOtherManagerCreator* someOtherManagerCreator() const;
private:
SomeManagerClassCreator* m_someManagerClassCreator;
SomeOtherManagerCreator* m_someOtherManagerCreator;
};
And TheManager will be created with TheCreator for internal creation:
class TheManager {
public:
TheManager(TheCreator*);
/* Rest of code from above */
};
The problem with this solution is that it violates DRY - for each class creator I would have to write setter/getter in TheCreator.
This seems like it would be a lot simpler with function templating as opposed to an Abstract Factory pattern
class ManagerFactory
{
public:
template <typename T> static BaseManager * getManager() { return new T();}
};
BaseManager * manager1 = ManagerFactory::template getManager<DerivedManager1>();
If you want to get them via a string, you can create a standard map from strings to function pointers. Here is an implementation that works:
#include <map>
#include <string>
class BaseManager
{
public:
virtual void doSomething() = 0;
};
class DerivedManager1 : public BaseManager
{
public:
virtual void doSomething() {};
};
class DerivedManager2 : public BaseManager
{
public:
virtual void doSomething() {};
};
class ManagerFactory
{
public:
typedef BaseManager * (*GetFunction)();
typedef std::map<std::wstring, GetFunction> ManagerFunctionMap;
private:
static ManagerFunctionMap _managers;
public:
template <typename T> static BaseManager * getManager() { return new T();}
template <typename T> static void registerManager(const std::wstring& name)
{
_managers[name] = ManagerFactory::template getManager<T>;
}
static BaseManager * getManagerByName(const std::wstring& name)
{
if(_managers.count(name))
{
return _managers[name]();
}
return NULL;
}
};
// the static map needs to be initialized outside the class
ManagerFactory::ManagerFunctionMap ManagerFactory::_managers;
int _tmain(int argc, _TCHAR* argv[])
{
// you can get with the templated function
BaseManager * manager1 = ManagerFactory::template getManager<DerivedManager1>();
manager1->doSomething();
// or by registering with a string
ManagerFactory::template registerManager<DerivedManager1>(L"Derived1");
ManagerFactory::template registerManager<DerivedManager2>(L"Derived2");
// and getting them
BaseManager * manager2 = ManagerFactory::getManagerByName(L"Derived2");
manager2->doSomething();
BaseManager * manager3 = ManagerFactory::getManagerByName(L"Derived1");
manager3->doSomething();
return 0;
}
EDIT: In reading the other answers I realized that this is very similar to Dave Van den Eynde's FactorySystem solution, but I'm using a function template pointer instead of instantiating templated factory classes. I think my solution is a little more lightweight. Due to static functions, the only object that gets instantiated is the map itself. If you need the factory to perform other functions (DestroyManager, etc.), I think his solution is more extensible.
You could implement an object factory with static methods that return an instance of a Manager-Class. In the factory you could create a method for the default type of manager and a method for any type of manager which you give an argument representing the type of the Manager-Class (say with an enum). This last method should return an Interface rather than a Class.
Edit: I'll try to give some code, but mind that my C++ times are quite a while back and I'm doing only Java and some scripting for the time being.
class Manager { // aka Interface
public: virtual void someMethod() = 0;
};
class Manager1 : public Manager {
void someMethod() { return null; }
};
class Manager2 : public Manager {
void someMethod() { return null; }
};
enum ManagerTypes {
Manager1, Manager2
};
class ManagerFactory {
public static Manager* createManager(ManagerTypes type) {
Manager* result = null;
switch (type) {
case Manager1:
result = new Manager1();
break;
case Manager2:
result = new Manager2();
break;
default:
// Do whatever error logging you want
break;
}
return result;
}
};
Now you should be able to call the Factory via (if you've been able to make the code sample work):
Manager* manager = ManagerFactory.createManager(ManagerTypes.Manager1);
I would use templates like this as I can't see the point of factories classes:
class SomeOtherManager;
class SomeManagerClass {
public:
SomeManagerClass(SomeOtherManager*);
virtual void someMethod1();
virtual void someMethod2();
};
class TheBaseManager {
public:
//
};
template <class ManagerClassOne, class ManagerClassOther>
class SpecialManager : public TheBaseManager {
public:
virtual ManagerClassOne* someManagerClass() const;
virtual ManagerClassOther* someOtherManager() const;
};
TheBaseManager* ourManager = new SpecialManager<SomeManagerClass,SomeOtherManager>;
You should take a look at the tutorial at
http://downloads.sourceforge.net/papafactory/PapaFactory20080622.pdf?use_mirror=fastbull
It contains a great tutorial on implementing an Abstract factory in C++ and the source code that comes with it is also very robust
Chris
Mh I don't understand a hundred percent, and I am not really into factory stuff from books and articles.
If all your managers share a similar interface you could derive from a base class, and use this base class in your program.
Depending on where the decision which class will be created will be made, you have to use an identifier for creation (as stated above) or handle the decision which manager to instantiate internally.
Another way would be to implement it "policy" like by using templates. So that You ManagerClass::create() returns a specific SomeOtherManagerWhatever instance. This would lay the decision which manager to make in the code which uses your Manager - Maye this is not intended.
Or that way:
template<class MemoryManagment>
class MyAwesomeClass
{
MemoryManagment m_memoryManager;
};
(or something like that)
With this construct you can easily use other managers by only changing the instantiation of MyAwesomeClass.
Also A class for this purpose might be a little over the top. In your case a factory function would do I guess. Well it's more a question of personal preference.
If you plan on supporting plugins that are dynamically linked, your program will need to provide a stable ABI (Application Binary Interface), that means that you cannot use C++ as your main interface as C++ has no standard ABI.
If you want plugins to implement an interface you define yourself, you will have to provide the header file of the interface to plugin programmer and standardize on a very simple C interface in order to create and delete the object.
You cannot provide a dynamic library that will allow you to "new" the plugin class as-is. That is why you need to standardize on a C interface in order to create the object. Using the C++ object is then possible as long as none of your arguments use possibly incompatible types, like STL containers. You will not be able to use a vector returned by another library, because you cannot ensure that their STL implementation is the same as yours.
Manager.h
class Manager
{
public:
virtual void doSomething() = 0;
virtual int doSomethingElse() = 0;
}
extern "C" {
Manager* newManager();
void deleteManager(Manager*);
}
PluginManager.h
#include "Manager.h"
class PluginManager : public Manager
{
public:
PluginManager();
virtual ~PluginManager();
public:
virtual void doSomething();
virtual int doSomethingElse();
}
PluginManager.cpp
#include "PluginManager.h"
Manager* newManager()
{
return new PluginManager();
}
void deleteManager(Manager* pManager)
{
delete pManager;
}
PluginManager::PluginManager()
{
// ...
}
PluginManager::~PluginManager()
{
// ...
}
void PluginManager::doSomething()
{
// ...
}
int PluginManager::doSomethingElse()
{
// ...
}
You didnt talk about TheManager. It looks like you want that to control which class is being used? or maybe you trying to chain them together?
It sounds like you need a abstract base class and a pointer to the currently used class. If you wish to chain you can do it in both abstract class and themanager class. If abstract class, add a member to the next class in chain, if themanager then sort it in order you which to use in a list. You'll need a way to add classes so you'll need an addMe() in themanager. It sounds like you know what your doing so w/e you choose should be right. A list with an addMe func is my recommendation and if you want only 1 active class then a function in TheManager deciding it would be good.
This maybe heavier than you need, but it sounds like you are trying to make a frame work class that supports plugins.
I would break it up into to 3 sections.
1) The FrameWork class would own the plugins.
This class is responsable for publishing interfaces supplied by the plugins.
2) A PlugIn class would own the componets that do the work.
This class is responsable for registering the exported interfaces, and binding the imported interfaces to the components.
3) The third section, the componets are the suppliers and consumers of the interfaces.
To make things extensible, getting things up and running might be broke up into stages.
Create everything.
Wire everything up.
Start everything.
To break things down.
Stop everything.
Destroy everything.
class IFrameWork {
public:
virtual ~IFrameWork() {}
virtual void RegisterInterface( const char*, void* ) = 0;
virtual void* GetInterface( const char* name ) = 0;
};
class IPlugIn {
public:
virtual ~IPlugIn() {}
virtual void BindInterfaces( IFrameWork* frameWork ) {};
virtual void Start() {};
virtual void Stop() {};
};
struct SamplePlugin :public IPlugIn {
ILogger* logger;
Component1 component1;
WebServer webServer;
public:
SamplePlugin( IFrameWork* frameWork )
:logger( (ILogger*)frameWork->GetInterface( "ILogger" ) ), //assumes the 'System' plugin exposes this
component1(),
webServer( component1 )
{
logger->Log( "MyPlugin Ctor()" );
frameWork->RegisterInterface( "ICustomerManager", dynamic_cast( &component1 ) );
frameWork->RegisterInterface( "IVendorManager", dynamic_cast( &component1 ) );
frameWork->RegisterInterface( "IAccountingManager", dynamic_cast( &webServer ) );
}
virtual void BindInterfaces( IFrameWork* frameWork ) {
logger->Log( "MyPlugin BindInterfaces()" );
IProductManager* productManager( static_cast( frameWork->GetInterface( "IProductManager" ) ) );
IShippingManager* shippingManager( static_cast( frameWork->GetInterface( "IShippingManager" ) ) );
component1.BindInterfaces( logger, productManager );
webServer.BindInterfaces( logger, productManager, shippingManager );
}
virtual void Start() {
logger->Log( "MyPlugin Start()" );
webServer.Start();
}
virtual void Stop() {
logger->Log( "MyPlugin Stop()" );
webServer.Stop();
}
};
class FrameWork :public IFrameWork {
vector plugIns;
map interfaces;
public:
virtual void RegisterInterface( const char* name, void* itfc ) {
interfaces[ name ] = itfc;
}
virtual void* GetInterface( const char* name ) {
return interfaces[ name ];
}
FrameWork() {
//Only interfaces in 'SystemPlugin' can be used by all methods of the other plugins
plugIns.push_back( new SystemPlugin( this ) );
plugIns.push_back( new SamplePlugin( this ) );
//add other plugIns here
for_each( plugIns.begin(), plugIns.end(), bind2nd( mem_fun( &IPlugIn::BindInterfaces ), this ) );
for_each( plugIns.begin(), plugIns.end(), mem_fun( &IPlugIn::Start ) );
}
~FrameWork() {
for_each( plugIns.rbegin(), plugIns.rend(), mem_fun( &IPlugIn::Stop ) );
for_each( plugIns.rbegin(), plugIns.rend(), Delete() );
}
};
Here's a minimal factory pattern implementation that I came up with in about 15 minutes. We use a similar one that uses more advanced base classes.
#include "stdafx.h"
#include <map>
#include <string>
class BaseClass
{
public:
virtual ~BaseClass() { }
virtual void Test() = 0;
};
class DerivedClass1 : public BaseClass
{
public:
virtual void Test() { } // You can put a breakpoint here to test.
};
class DerivedClass2 : public BaseClass
{
public:
virtual void Test() { } // You can put a breakpoint here to test.
};
class IFactory
{
public:
virtual BaseClass* CreateNew() const = 0;
};
template <typename T>
class Factory : public IFactory
{
public:
T* CreateNew() const { return new T(); }
};
class FactorySystem
{
private:
typedef std::map<std::wstring, IFactory*> FactoryMap;
FactoryMap m_factories;
public:
~FactorySystem()
{
FactoryMap::const_iterator map_item = m_factories.begin();
for (; map_item != m_factories.end(); ++map_item) delete map_item->second;
m_factories.clear();
}
template <typename T>
void AddFactory(const std::wstring& name)
{
delete m_factories[name]; // Delete previous one, if it exists.
m_factories[name] = new Factory<T>();
}
BaseClass* CreateNew(const std::wstring& name) const
{
FactoryMap::const_iterator found = m_factories.find(name);
if (found != m_factories.end())
return found->second->CreateNew();
else
return NULL; // or throw an exception, depending on how you want to handle it.
}
};
int _tmain(int argc, _TCHAR* argv[])
{
FactorySystem system;
system.AddFactory<DerivedClass1>(L"derived1");
system.AddFactory<DerivedClass2>(L"derived2");
BaseClass* b1 = system.CreateNew(L"derived1");
b1->Test();
delete b1;
BaseClass* b2 = system.CreateNew(L"derived2");
b2->Test();
delete b2;
return 0;
}
Just copy & paste over an initial Win32 console app in VS2005/2008. I like to point out something:
You don't need to create a concrete factory for every class. A template will do that for you.
I like to place the entire factory pattern in its own class, so that you don't need to worry about creating factory objects and deleting them. You simply register your classes, a factory class gets created by the compiler and a factory object gets created by the pattern. At the end of its lifetime, all factories are cleanly destroyed. I like this form of encapsulation, as there is no confusion over who governs the lifetime of the factories.