I have a c++ class:
Class farm {
...
protected:
vector<ff_node*> workers;
};
//ff_node an abstract method representing a single thread
class ff_node {
protected:
//svc is the method to encapsulate a sequential function
void* svc(void *)=0;
};
Class farm_withMoreWorkers: public farm {
void addWorker(){
ff_node *newWorker;
newWorker=new ff_node();// rather than adding ff_node make the instance type as that of type workers since ff_node is abstract
farm:: workers.push_back(newWorker);
}
};
The class ff_node is abstract . In order to add one more worker, I need to create a new instance whose type is the same as the others (all of the workers are of the same type)
Is there a way to get the specific type of (one of the) workers and create an instance of that type?!
Create a pure virtual clone function in the base class and override it in every derived class.
class ff_node
{
public:
virtual ff_node* clone() = 0;
};
class ff_child : public ff_node
{
public:
ff_node* clone() override {new ff_child;}
};
Now, given a ff_node* node, you can create another instance of the same runtime type by calling node->clone().
You gave very little info, so I'm speculating as to what you actually want. Suppose there is an abstract (pure virtual) class
class worker { /* define some useful virtual interface */ };
and you want to use several polymorphism to use several differernt workers. Then you best keep them in a vector of unique_ptr, so that at the end of the vector's scope the workers are automatically deleted. You can add a new worker by directly constructing it from arguments provided by the user. Since the type of the new worker may not even be known at the time of definition of the farm, this functionality must be provided as template. For example
class farm
{
std::vector<std::unique_ptr<worker>> workers; //
public:
// constructs new worker of type Worker with arguments provided
template<typename Worker, typename... Args>
void add_worker(Args&&...args)
{ workers.emplace_back(new Worker(std::forward<Args>(args)...)); }
};
and use it like this
struct builder : public worker
{
builder(string const&, const widget*, some_type);
/* ... */
};
farm the_farm;
widget w( /* ... */ );
some_type x;
the_farm.add<builder>("the new builder", &w, x);
Note that in the call to farm::add() only the first template parameter must be provided, the others will be deduced from the function arguments.
Related
Suppose that I have a Task class:
class Task;
using FinishedCallback = void (Task &);
class Task {
public:
// this function is implemented by derived classes
// there are other virtual functions too
virtual bool isFinished() = 0;
private:
std::vector<FinishedCallback> m_callbacks;
protected:
// these functions are called by derived classes
void addFinishedCallback(FinishedCallback callback) {
m_callbacks.push_back(callback);
}
void callFinishedCallbacks();
};
This class is the base class. I'd like to put as much implementation as possible into it. It has a m_callbacks vector, which stores the callbacks which are needed to be called when the task is finished (callFinishedCallbacks() does this).
Now, derive from this class:
class MyTask;
using MyFinishedCallback = void (MyTask &);
class MyTask: public Task {
public:
void addFinishedCallback(MyFinishedCallback callback) {
Task::addFinishedCallback(reinterpret_cast<FinishedCallback &>(callback));
}
// when MyTask finishes, it calls callFinishedCallbacks
};
Here, the finished callback has MyTask & parameter, so I have to reinterpret_cast it. So my program has UB. (The reason of the MyTask & type is that I don't have to cast Task & to MyTask & in the callback - it is for convenience).
But, even my program has UB, it works (the only real problem I could have if MyTask had multiple inheritance). Is it possible to modify this program to remove UB, while retaining its main attributes:
(compiled) code is small
small amount of coding work needed, if one derives from Task
no wrappers needed for callbacks
One idea would be to make a slight change to how you write your callbacks.
Use Task * rather than Task & as the callback parameter type.
At the beginning of the callback, use dynamic_cast to turn the Task * into a pointer to the derived type (MyType *).
void MyCallback(Task *task) {
auto *mytask = dynamic_cast<MyTask *>(task);
assert(mytask != nullptr);
// use mytask from here on
}
Another idea would be to use the Curiously Recurring Template Pattern (CRTP).
class BasicTask {
public:
virtual ~BasicTask() = default;
virtual bool isFinished() = 0;
};
template <typename Self>
class Task : public BasicTask {
private:
typedef void FinishedCallback(Self &task);
std::vector<FinishedCallback> m_callbacks;
protected:
void addFinishedCallback(FinishedCallback callback) {
m_callbacks.push_back(callback);
}
void callFinishedCallbacks();
};
Then you'd derive your specific task types from Task like this:
class MyTask : public Task<MyTask> { ... };
This reduced the amount of code you have to write (because there's only one source code implementation of addFinishedCallback), but it runs the risk of generating more object code. The optimizer and linker might be able to reign in that possibility.
I have a composite pattern implementation, used for GUI components:
class CObject {
private:
CObject * m_pParent;
CObjectContainer * m_pChildren;
void private_foo() {
this->foo();
//Calls private_foo for each child in container.
m_pChildren->foo();
}
public:
virtual void foo() {
//empty for base class
}
virtual CObject * duplicate() {
//Do duplication code
return new CObject(*this);
}
virtual CObject * detach() {
//Remove this object (along with it's children)
//from current tree.
m_pParent->RemoveChild(this);
m_pParent = nullptr;
return this;
}
}
class CSpecificObject : public CObject {
public:
virtual void foo() {
//Specific code for this class
}
virtual CSpecificObject * duplicate() {
//Overload, but the code only calls diferent constructor
return new CSpecificObject(*this);
}
virtual CSpecificObject * detach() {
//Note the code is identical.
m_pParent->RemoveChild(this);
m_pParent = nullptr;
return this;
}
}
Unfortunately the number of inherited classes increases rapidly and the duplicate code (in given example only the detach() method) is giving me a headache.
Is there a way to cleanly implement detach() methods, keeping the return type the same as the object, on which it is called?
I was thinking about CRTP, but I can not think of a way to keep the dynamic polymorphism along with compile time polymorphism:
template <Child>
class CObject {
private:
...
Child * detach() {
m_pParent->RemoveChild(this);
m_pParent = nullptr;
return static_cast<Child*>(this);
}
...
}
//Array of CObject* pointers is no longer possible.
You can add one level of abstraction:
class CObjectBase
{
public:
// Other methods...
virtual CObjectBase* detach() = 0;
virtual CObjectBase* duplicate() const = 0;
};
template <typename Child>
class CObject : public CObjectBase
{
public:
// ...
Child* duplicate() const
{
return new Child(*static_cast<Child*>(this));
}
Child* detach()
{
m_pParent->RemoveChild(this);
m_pParent = nullptr;
return static_cast<Child*>(this); // Cast needed here (inherent to CRTP)
}
std::vector<CObjectBase*> children; // Array possible now
// ...
};
class MyObject : public CObject<MyObject>
{
// ...
};
In natural language: an interface for all objects (CObjectBase) have a partial implementation for its descendants (CObject<Child>), which just have to inherit this partial implementation, decreasing the amount of replicated code.
I was thinking about CRTP, but I can not think of a way to keep the dynamic polymorphism along with compile time polymorphism
You can mix them by providing default virtual implementations for certain interfaces using CRTP style base classes.
Thus you have the possibility to aggregate CRTP base implementations (maybe configured with additional 'policy'-template parameters) and still being able to override particular behavior in inherited classes.
Microsoft's ATL library uses this a lot.
I also make use of this technique in my STTCL state machine library.
From the snippet alone it is unclear why you need detach() to return a pointer to a delivered type.
To take advantage of detach() returning a delivered type, it needs to be called using a reference to the delivered type anyway. Like this:
CSpecificObject* specific_object = new SpecificObject();
// ...
specific_object->detach()->method_declared_in_specific_object();
But this can be replaced with equivalent that works even if detach is void:
specific_object->detach();
specific_object->method_declared_in_specific_object();
If you have a reference to the base type, you can't take advantage of detach() return type:
CObject* specific_object = new SpecificObject();
//...
// !!! Won't compile:
specific_object->detach()->method_declared_in_specific_object();
For this reason it is unclear what are the advantages of the approach you are trying to implement.
A side not is that the duplicate() method is smelly. It breaks when delivered class does not overwrite it, but uses the default implementation from the parent class. It can be a sign that something is wrong with the high level design.
I've built a small, limited-scope, cross-platform UI library in C++. It uses the following classes to handle UI callbacks:
// Base class for templated __Callback class to allow for passing __Callback
// objects as parameters, storing in containers, etc. (as Callback*)
class Callback
{
public:
virtual void execute() = 0;
virtual ~Callback() { }
protected:
Callback() { }
};
As the comment describes, this is the base class for callbacks - which allows for passing them as arguments and storing them inside UI widgets such that the proper callback can be executed (when, for example, a user clicks a button).
// C++ has no callbacks (in the sense of an action [method] of a
// target [object]), so we had to roll our own. This class can be used
// directly, but the NEW_CALLBACK macro is easier.
template <class __TargetType>
class __Callback : public Callback
{
public:
typedef __TargetType TargetType;
typedef void (TargetType::*ActionType)(void);
virtual void execute()
{
(this->__target->*this->__action)();
}
__Callback(TargetType* target_, ActionType action_) :
Callback(), __target(target_), __action(action_) { }
virtual ~__Callback() { }
private:
// target object for the callback
TargetType* __target;
// action (method) of the target that will be called
ActionType __action;
};
This templated class is the meat of the callback paradigm. It stores a pointer to an object and a pointer to a member function, such that the member function can be called on the target object at a later time.
#define NEW_CALLBACK(class_, obj_, act_) \
new __Callback<class_>(obj_, &class_::act_)
This macro just makes it a little easier to create a templated __Callback object.
This has been working great for a long while! A button with a callback might be instantiated like:
MyClass* obj = new MyClass();
Button* btn = new Button("Title", NEW_CALLBACK(MyClass, obj, btnClicked));
This would create a button, to be placed in a window or other container at a later time, and when clicked it will call obj->btnClicked().
Now, my question (sorry for the lengthy setup, I don't think I could pare it down any more than this). A case has arisen where I need to copy a Callback* object. Of course, since it's just a pointer to the base class, I can't determine the type of the templated derived class.
How would one go about copying an arbitrary Callback object, with the copy pointing to the same target and action as the original? Or, is there an entirely different approach to this callback problem that I should be taking (though I would prefer not to change it too much)?
Thanks all!
I don't know if there's a better approach that you should take, but this seems like an ideal use for a clone method.
You simply need to define a copy constructor in your __Callback template, define a pure virtual Clone method in your base class, and then implement that virtual method in your template (making use of the copy constructor that you've created)
For example:
class Callback
{
public:
...
virtual Callback* Clone()=0;
};
template <class __TargetType>
class __Callback : public Callback
{
public:
...
__Callback(const __Callback& other) :
__target(other.target_), __action(other.action_) { }
virtual Callback* Clone()
{
return new __Callback(this);
}
}
Use clone as a replacement for virtual constructors. Notice the
co-variant return types that make this really work. e.g.
struct Callback {
virtual Callback* clone() const;
};
template<...>
struct Callback_impl {
virtual Callback_impl* clone() const;
};
You should also think about shared_ptr for lifetime management. All
this seems a little fragile.
To me it looks like you want std::function . It is polymorphic, type-safe and works with pointers to member functions through std::mem_fn.
In my design, there is a class which reads information from file. The read info represents a job (for simplicity, it's an integer, which is "job id"). The file reader class can accept objects which can handle such a job. Now my idea was, to make an Interface, e.g. "IJobHandler" which has a pure virtual function "DoJob()" and then you can call something like
FileReader fr;
Class1 c1; // has a base class IAcceptor with virtual method HandleJobId()
Class2 c2; // has a base class IAcceptor with virtual method HandleJobId()
fr.Register(c1);
fr.Register(c2);
fr.doJob(1); // calls c1.HandleJobId()
fr.doJob(2); // class c2.HandleJobId()
This would work fine. But what happens, if some class can handle two or more job ids? But there is only one method which this class can implement (HandleJobId()). Wouldn't the following be nice:
fr.Register(c1, c1::Handle_1()) or something like that?
Maybe my intention is not very clear right now. But you will se it on the bigger code example below. Sorry for the big code block, but I don't know how to explain it that exactly...
class IAcceptable
{
public:
// interface; implementors should return map of job-ids (int)
// and a kind of pointer to a method which should be called to
// handle the job.
virtual std::map<int, SOME_KIND_OF_FUNCTION_POINTER> GetJobIds() const = 0;
};
class Class12 : public IAcceptable
{
public:
void Handle_1(){} // method to handle job id 1
void Handle_2(){} // method to handle job id 2
virtual std::map<int, SOME_KIND_OF_FUNCTION_POINTER> GetJobIds() const
{
std::map<int, SOME_KIND_OF_FUNCTION_POINTER> intToMethodMap;
// return map, which says: "I can handle job id 1, by calling Handle_1(), so I give you c12 pointer to this method"
// (same thing for job id 2 and Handle_2())
intToMethodMap.insert(std::pair<int, SOME_KIND_OF_FUNCTION_POINTER>(1, POINTER_TO_Handle_1);
intToMethodMap.insert(std::pair<int, SOME_KIND_OF_FUNCTION_POINTER>(2, POINTER_TO_Handle_2);
return intToMethodMap;
}
};
class Class34 : public IAcceptable
{
void Handle_3(){} // method to handle job id 3
void Handle_4(){} // method to handle job id 4
virtual std::map<int, SOME_KIND_OF_FUNCTION_POINTER> GetJobIds() const
{
std::map<int, SOME_KIND_OF_FUNCTION_POINTER> intToMethodMap;
// return map, which says: "I can handle job id 3, by calling Handle_3(), so I give you c12 pointer to this method"
// (same thing for job id 4 and Handle_4())
intToMethodMap.insert(std::pair<int, SOME_KIND_OF_FUNCTION_POINTER>(3, POINTER_TO_Handle_3);
intToMethodMap.insert(std::pair<int, SOME_KIND_OF_FUNCTION_POINTER>(4, POINTER_TO_Handle_4);
return intToMethodMap;
}
};
class FileReader
{
public:
// register an IAcceptable
// and add its handlers to the local list
void Register(const IAcceptable& acc)
{
m_handlers.insert(acc.GetJobIds());
}
// if some job is to do, search for the job id and call
// the found function
void doSomeJob(int i)
{
std::map<int, SOMEFUNCTION>::iterator specificHandler = m_handlers.find(i);
// call here (specificHandler->second)()
}
private:
std::map<int, SOMEFUNCTION> m_handlers;
};
int main()
{
Class12 c12; // can handle job id 1 and 2
Class34 c34; // can handle job id 3 and 4
FileReader fr;
fr.Register(c12);
fr.Register(c34);
fr.doSomeJob(1); // should lead to this call: c12->Handle_1()
fr.doSomeJob(2); // c12->Handle_2();
fr.doSomeJob(3); // c34->Handle_3();
fr.doSomeJob(4); // c34->Handle_4();
}
Well, maybe the design is my problem and someone can give me a hint how to make it better :)
Here's a complete example:
class IAcceptable;
class DelegateBase
{
public:
virtual void Call() = 0;
};
template <class Class> class Delegate: public DelegateBase
{
public:
typedef void (Class::*Function)();
Delegate(Class* object, Function f): func(f) {}
virtual void Call() { (object->*func)(); }
private:
Class* object;
Function func;
};
class IAcceptable
{
public:
// interface; implementors should return map of job-ids (int)
// and a kind of pointer to a method which should be called to
// handle the job.
virtual std::map<int, DelegateBase*> GetJobIds() = 0;
};
class Class12 : public IAcceptable
{
public:
void Handle_1(){} // method to handle job id 1
void Handle_2(){} // method to handle job id 2
virtual std::map<int, DelegateBase*> GetJobIds()
{
std::map<int, DelegateBase*> intToMethodMap;
// return map, which says: "I can handle job id 1, by calling Handle_1(), so I give you c12 pointer to this method"
// (same thing for job id 2 and Handle_2())
intToMethodMap.insert(std::pair<int, DelegateBase*>(1, new Delegate<Class12>(this, &Class12::Handle_1)));
intToMethodMap.insert(std::pair<int, DelegateBase*>(2, new Delegate<Class12>(this, &Class12::Handle_2)));
return intToMethodMap;
}
};
class Class34 : public IAcceptable
{
void Handle_3(){} // method to handle job id 3
void Handle_4(){} // method to handle job id 4
virtual std::map<int, DelegateBase*> GetJobIds()
{
std::map<int, DelegateBase*> intToMethodMap;
// return map, which says: "I can handle job id 3, by calling Handle_3(), so I give you c12 pointer to this method"
// (same thing for job id 4 and Handle_4())
intToMethodMap.insert(std::pair<int, DelegateBase*>(3, new Delegate<Class34>(this, &Class34::Handle_3)));
intToMethodMap.insert(std::pair<int, DelegateBase*>(4, new Delegate<Class34>(this, &Class34::Handle_4)));
return intToMethodMap;
}
};
class FileReader
{
public:
// register an IAcceptable
// and add its handlers to the local list
void Register(IAcceptable& acc)
{
std::map<int, DelegateBase*> jobIds = acc.GetJobIds();
m_handlers.insert(jobIds.begin(), jobIds.end());
}
// if some job is to do, search for the job id and call
// the found function
void doSomeJob(int i)
{
std::map<int, DelegateBase*>::iterator specificHandler = m_handlers.find(i);
specificHandler->second->Call();
}
private:
std::map<int, DelegateBase*> m_handlers;
};
int _tmain(int argc, _TCHAR* argv[])
{
Class12 c12; // can handle job id 1 and 2
Class34 c34; // can handle job id 3 and 4
FileReader fr;
fr.Register(c12);
fr.Register(c34);
fr.doSomeJob(1); // should lead to this call: c12->Handle_1()
fr.doSomeJob(2); // c12->Handle_2();
fr.doSomeJob(3); // c34->Handle_3();
fr.doSomeJob(4); // c34->Handle_4();
return 0;
}
To call a member function we need an object; so your maps should contain not simply method pointers, but something that can encapsulate a complete call: an object + a method pointer. That something is Delegate here.
To make sure that the method is called correctly even if it's defined in a subclass, we need to store both the derived object and the method pointer type-correctly (no casting). So we make Delegate a template, with the derived class as its parameter.
This means that delegates based on methods of different subclasses are incompatible, and cannot be put into a map. To work around this we introduce a common base class, DelegateBase, and the virtual function Call(). Call() can be called without knowing the exact type of stored object / method, and it will be dispatched to a type-correct implementation. Now we can store DelegateBase* pointers in the map.
Also check out boost::function and boost::bind, they provide a generalization for the above, and I think they could also be used to your purposes.
There are several solutions to this sort of problem.
If you have a class which can handle several different jobs, in separate
functions, the simplest solution is to wrap it, several types, e.g.:
class JobsOneAndTwo
{
public:
void doJobOne();
void doJobTwo();
};
class JobOne : public AbstractJob, JobsOneAndTwo
{
public:
virtual void doJob() { doJobOne(); }
};
class JobTwo : public AbstractJob, JobOneAndTwo
{
public:
virtual void doJob() { doJobTwo(); }
};
If this occurs often in the set of jobs, you can create a template (over
two or moer member function pointers) to generate the individual wrapper
functions.
Alternatively, you can dispatch on a data member of the class:
class JobOneAndTwo : public AbstractJob
{
int myJob;
public:
JobOneAndTwo(int id) : myJob( id ) {}
void JobOne();
void JobTwo();
virtual void doJob()
{
switch ( myJob ) {
case 1:
JobOne();
break;
case 2:
JobTwo();
break;
}
};
In this case, you instantiate the class twice, each time passing a
different argument to the constructor.
In most of the cases I've seen, when one class can handle two jobs, it's
because the two jobs differ only in some parameters; this is really just
a variant on the second solution above, except that you don't switch to
call different member functions, you simply use the parameters (passed
into the constructor) in the basic function.
More generally, don't forget that your concrete job classes can have
data, and their behavior can be modified by such data. And that you can
register multiple instances of a single class, with different data.
So you say that you have many handlers, each of which can handle an arbitrary number of job IDs, and you want to register an arbitrary number of handlers and let all of them which apply handle a given job.
To that end, let every handler implement this interface:
struct Handler
{
virtual bool canHandle(job_id_t id) const = 0;
virtual void doJob(job_it_t id) = 0;
};
To register a handler, simply store a pointer in a container:
std::vector<Handler*> handlers;
Then, if you need to do a job, iterate the container and dispatch:
handleJob(job_it_t id)
{
for (std::vector<Handler*>::iterator it = handlers.begin(), end = handlers.end(); it != end; ++it)
{
if ((*it)->canHandle(id))
(*it)->doJob(id);
}
}
typedef void (IAccaptable::*SOME_KIND_OF_FUNCTION_POINTER)();
...
Register(1, (SOME_KIND_OF_FUNCTION_POINTER)(&Class12::Handle1));
Warning: this C-style cast will only work with single inheritance. (Well, actually the cast would compile just fine with multiple inheritance too, but when calling (derivedObject->*funcPtr)() with a funcPtr that points at a member function of a non-first base class, then it would be called without the derivedObject pointer having been properly adjusted to point at the proper subobject belonging to that base, most probably resulting in a crash.)
A better, but more complicated solution would be to register small caller objects instead of member function pointers. When calling the handler functions, these caller objects could appropriately cast the target object.
class CallerBase
{
public:
virtual void Call(Base* object) = 0;
};
template <class Derived>
struct Caller: public CallerBase
{
public:
typedef void (Derived::*Function)();
Caller(Function f): func(f) {}
virtual void Call(Base* object)
{
Derived* derived = static_cast<Derived*>(object);
(derived->*func)();
}
private:
Function func;
};
Register(1, new Caller<Derived>(&Derived::F));
Then your map would contain CallerBase* pointers, and once you find the proper caller, you'd do caller->Call(object). If object in this call is a Derived*, then it will be implicitly cast to Base*, but the virtual Caller<Derived>::Call() function will cast it back to Derived* before actually calling the method.
Method pointers can be a lot of fun.
I don't want to self promote myself but check out my guide on them I wrote back in school.
http://nicolong.com/code-examples/menu-object-tutorial
Might help a little.
EDIT: minor fixes (virtual Print; return mpInstance) following remarks in the answers.
I am trying to create a system in which I can derive a Child class from any Base class, and its implementation should replace the implementation of the base class.
All the objects that create and use the base class objects shouldn't change the way they create or call an object, i.e. should continue calling BaseClass.Create() even when they actually create a Child class.
The Base classes know that they can be overridden, but they do not know the concrete classes that override them.
And I want the registration of all the the Child classes to be done just in one place.
Here is my implementation:
class CAbstractFactory
{
public:
virtual ~CAbstractFactory()=0;
};
template<typename Class>
class CRegisteredClassFactory: public CAbstractFactory
{
public:
~CRegisteredClassFactory(){};
Class* CreateAndGet()
{
pClass = new Class;
return pClass;
}
private:
Class* pClass;
};
// holds info about all the classes that were registered to be overridden
class CRegisteredClasses
{
public:
bool find(const string & sClassName);
CAbstractFactory* GetFactory(const string & sClassName)
{
return mRegisteredClasses[sClassName];
}
void RegisterClass(const string & sClassName, CAbstractFactory* pConcreteFactory);
private:
map<string, CAbstractFactory* > mRegisteredClasses;
};
// Here I hold the data about all the registered classes. I hold statically one object of this class.
// in this example I register a class CChildClass, which will override the implementation of CBaseClass,
// and a class CFooChildClass which will override CFooBaseClass
class RegistrationData
{
public:
void RegisterAll()
{
mRegisteredClasses.RegisterClass("CBaseClass", & mChildClassFactory);
mRegisteredClasses.RegisterClass("CFooBaseClass", & mFooChildClassFactory);
};
CRegisteredClasses* GetRegisteredClasses(){return &mRegisteredClasses;};
private:
CRegisteredClasses mRegisteredClasses;
CRegisteredClassFactory<CChildClass> mChildClassFactory;
CRegisteredClassFactory<CFooChildClass> mFooChildClassFactory;
};
static RegistrationData StaticRegistrationData;
// and here are the base class and the child class
// in the implementation of CBaseClass::Create I check, whether it should be overridden by another class.
class CBaseClass
{
public:
static CBaseClass* Create()
{
CRegisteredClasses* pRegisteredClasses = StaticRegistrationData.GetRegisteredClasses();
if (pRegisteredClasses->find("CBaseClass"))
{
CRegisteredClassFactory<CBaseClass>* pFac =
dynamic_cast<CRegisteredClassFactory<CBaseClass>* >(pRegisteredClasses->GetFactory("CBaseClass"));
mpInstance = pFac->CreateAndGet();
}
else
{
mpInstance = new CBaseClass;
}
return mpInstance;
}
virtual void Print(){cout << "Base" << endl;};
private:
static CBaseClass* mpInstance;
};
class CChildClass : public CBaseClass
{
public:
void Print(){cout << "Child" << endl;};
private:
};
Using this implementation, when I am doing this from some other class:
StaticRegistrationData.RegisterAll();
CBaseClass* b = CBaseClass::Create();
b.Print();
I expect to get "Child" in the output.
What do you think of this design? Did I complicate things too much and it can be done easier? And is it OK that I create a template that inherits from an abstract class?
I had to use dynamic_pointer (didn't compile otherwise) - is it a hint that something is wrong?
Thank you.
This sort of pattern is fairly common. I'm not a C++ expert but in Java you see this everywhere. The dynamic cast appears to be necessary because the compiler can't tell what kind of factory you've stored in the map. To my knowledge there isn't much you can do about that with the current design. It would help to know how these objects are meant to be used. Let me give you an example of how a similar task is accomplished in Java's database library (JDBC):
The system has a DriverManager which knows about JDBC drivers. The drivers have to be registered somehow (the details aren't important); once registered whenever you ask for a database connection you get a Connection object. Normally this object will be an OracleConnection or an MSSQLConnection or something similar, but the client code only sees "Connection". To get a Statement object you say connection.prepareStatement, which returns an object of type PreparedStatement; except that it's really an OraclePreparedStatement or MSSQLPreparedStatement. This is transparent to the client because the factory for Statements is in the Connection, and the factory for Connections is in the DriverManager.
If your classes are similarly related you may want to have a function that returns a specific type of class, much like DriverManager's getConnection method returns a Connection. No casting required.
The other approach you may want to consider is using a factory that has a factory-method for each specific class you need. Then you only need one factory-factory to get an instance of the Factory. Sample (sorry if this isn't proper C++):
class CClassFactory
{
public:
virtual CBaseClass* CreateBase() { return new CBaseClass(); }
virtual CFooBaseClass* CreateFoo() { return new CFooBaseClass();}
}
class CAImplClassFactory : public CClassFactory
{
public:
virtual CBaseClass* CreateBase() { return new CAImplBaseClass(); }
virtual CFooBaseClass* CreateFoo() { return new CAImplFooBaseClass();}
}
class CBImplClassFactory : public CClassFactory // only overrides one method
{
public:
virtual CBaseClass* CreateBase() { return new CBImplBaseClass(); }
}
As for the other comments criticizing the use of inheritance: in my opinion there is no difference between an interface and public inheritance; so go ahead and use classes instead of interfaces wherever it makes sense. Pure Interfaces may be more flexible in the long run but maybe not. Without more details about your class hierarchy it's impossible to say.
Usually, base class/ derived class pattern is used when you have an interface in base class, and that interface is implemented in derived class (IS-A relationship). In your case, the base class does not seem to have any connection with derived class - it may as well be void*.
If there is no connection between base class and derived class, why do you use inheritance? What is the benefit of having a factory if factory's output cannot be used in a general way? You have
class CAbstractFactory
{
public:
virtual ~CAbstractFactory()=0;
};
This is perfectly wrong. A factory has to manufacture something that can be used immediately:
class CAbstractFactory
{
public:
virtual ~CAbstractFactory(){};
public:
CBaseClass* CreateAndGet()
{
pClass = new Class;
return pClass;
}
private:
CBaseClass* pClass;
protected:
CBaseClass *create() = 0;
};
In general, you're mixing inheritance, virtual functions and templates the way they should not be mixed.
Without having read all of the code or gone into the details, it seems like you should've done the following:
make b of type CChildClass,
make CBaseClass::Print a virtual function.
Maybe I'm wrong but I didn't find any return statement in your CBaseClass::Create() method!
Personally, I think this design overuses inheritance.
"I am trying to create a system in which I can derive a Child class from any Base class, and its implementation should replace the implementation of the base class." - I don't know that IS-A relationships should be that flexible.
I wonder if you'd be better off using interfaces (pure virtual classes in C++) and mixin behavior. If I were writing it in Java I'd do this:
public interface Foo
{
void doSomething();
}
public class MixinDemo implements Foo
{
private Foo mixin;
public MixinDemo(Foo f)
{
this.mixin = f;
}
public void doSomething() { this.mixin.doSomething(); }
}
Now I can change the behavior as needed by changing the Foo implementation that I pass to the MixinDemo.