I'm experiencing a challenging problem, which has not been solvable - hopefully until now. I'm developing my own framework and therefore trying to offer the user flexibility with all the code complexity under the hood.
First of all I have an abstract base class which users can implement, obviously simplified:
class IStateTransit
{
public:
bool ConnectionPossible(void) = 0;
}
// A user defines their own class like so
class MyStateTransit : public IStateTransit
{
public:
bool ConnectionPossible(void){ return true; }
}
Next, I define a factory class. Users can register their own custom state transit objects and refer to them later by simply using a string identifier they have chosen:
class TransitFactory : public Singleton<TransitFactory>
{
public:
template<typename T> void RegisterStateTransit(const string& name)
{
// If the transit type is not already registered, add it.
if(transits.find(name) == transits.end())
{
transits.insert(pair<string, IStateTransit*>(name, new T()));
};
}
IStateTransit* TransitFactory::GetStateTransit(const string& type) const
{
return transits.find(type)->second;
};
private:
map<string, IStateTransit*> transits;
}
Now the problem is (probably obviously) that whenever a user requests a transit by calling GetStateTransit the system currently keeps returning the same object - a pointer to the same object that is. I want to change this.
PROBLEM: How can I return a new (clone) of the original IStateTransit object without the user having to define their own copy constructor or virtual constructor. Ideally I would somehow like the GetStateTransit method to be able to cast the IStateTransit object down to the derived type it is at runtime and return a clone of that instance. The biggest hurdle is that I do not want the user to have to implement any extra (and probably complex) methods.
4 hours of Googling and trying has led me nowhere. The one who has the answer is a hero!
The problem is that you don't have the type information to perform the clone as you only have a pointer to base class type and no knowledge as to what derived types have been implemented and are available.
I think there's a reason that 4 hours of googling haven't turned anything up. If you want IStateTransit to be cloneable you have to have an interface where the derived class implementer provides some sort of clone method implementation.
I'm sorry if this isn't what you wanted to hear.
However, implementing a clone method shouldn't be a big burden. Only the class implementor knows how a class can be copied, given a correct copy constructor, clone can be implemented for a leaf-node class like this:
Base* clone() const
{
return new MyType(*this);
}
You could even macro-alize it; although I wouldn't.
If I understand the problem correctly, you shouldn't insert new T -s into the map, but rather objects that create new T-s.
struct ICreateTransit
{
virtual ~ICreateTransit() {}
virtual IStateTransite* create() const = 0;
};
template <class T>
struct CreateTransit: public ICreateTransit
{
virtual IStateTransit* create() const { return new T(); }
};
And now insert:
transits.insert(pair<string, ICreateTransit*>(name, new CreateTransit<T>()));
And retrieve "copies" with:
return transits.find(type)->second->create(); //hopefully with error handling
It shouldn't be impossible to modify StateTransit<T> so it holds a T of which to make copies of, should the default one not do.
I think the general name for techniques like this is called "type erasure" (derived types "remember" particular types, although the base class is unaware of those).
This problem to me sounds that the abstract factory pattern might be of help. Using this pattern the libraries client can define how your framework builds its types. The client can inject his own subclass of the factory into the framework and define there what types should be build.
What you need is (additionaly)
A base class for the factory
As a client: Derive a concrete factory
A way to inject (as a client) a subtype of the factory into the framework
Call the factory metods to create new types.
Does this help you?
Related
I am working on an api, which during runtime decides which higher-level api to use, I have many abstract classes, and derived classes for each high-level api, and a context class which provides me with the correct derived classes for the job, using a function (for example):
Mesh* genMesh(data d) { if(m_useA_API) return new A_mesh(d); else return B_mesh(d); }
something like that, now the question is, is it possible to make the code less ugly ? and instead of using methods inside the context class, can I override new operator in the base class to return the appropriate derived class instance?
if not, what are some possible solutions?
tl;dr this is what i'd like to do
Mesh* m = new Mesh(data); // and the base class decides which derived class to use instead of the Context class.
Thanks.
You can not use new as factory, but you could use Implementation Pattern for it:
class Mesh {
std::unique_ptr<MeshImpl> _impl;
public:
Mesh(int data)
: _impl(
m_use_A_API
? new A_mesh(data)
: new B_mesh(data)
) {
}
MeshImpl& get_value() { return *_impl; }
};
Classes A_mesh, B_mesh are different classes that inherited from class MeshImpl and will be initialized by correct way;
Or you can improve your factory code by next way:
move your method genMesh(int) inside class Mesh
make constructors of Mesh private, for be sure that nobody call it directly.
I am a relatively new C++ programmer.
In writing some code I've created something similar in concept to the code below. When a friend pointed out this is in fact a factory pattern I read about the pattern and saw it is in similar.
In all of the examples I've found the factory pattern is always implemented using a separate class such as class BaseFactory{...}; and not as I've implemented it using a static create() member function.
My questions are:
(1) Is this in fact a factory pattern?
(2) The code seems to work. Is there something incorrect in the way I've implemented it?
(3) If my implementation is correct, what are the pros/cons of implementing the static create() function as opposed to the separate BaseFactory class.
Thanks!
class Base {
...
virtual ~Base() {}
static Base* create(bool type);
}
class Derived0 : public Base {
...
};
class Derived1 : public Base {
...
};
Base* Base::create(bool type) {
if(type == 0) {
return new Derived0();
}
else {
return new Derived1();
}
}
void foo(bool type) {
Base* pBase = Base::create(type);
pBase->doSomething();
}
This is not a typical way to implement the factory pattern, the main reason being that the factory class isn't typically a base of the classes it creates. A common guideline for when to use inheritance is "Make sure public inheritance models "is-a"". In your case this means that objects of type Derived0 or Derived1 should also be of type Base, and the derived classes should represent a more specialised concept than the Base.
However, the factory pattern pretty much always involves inheritance as the factory will return a pointer to a base type (yous does this too). This means the client code doesn't need to know what type of object the factory created, only that it matches the base class's interface.
With regard to having a static create functions, it depends on the situation. One advantage, as your example shows, is that you won't need to create an instance of the factory in order to use it.
Your factory is ok, except for the fact that you merged the factory and the interface, breaking the SRP principle.
Instead of making the create static method in the base class, create it in another (factory) class.
My first foray in to C++ is building an audio synthesis library (EZPlug).
The library is designed to make it easy to set up a graph of interconnected audio generator and processor objects. We can call the EZPlugGenerators
All of the processor units can accept one or more EZPlugGenerators as inputs.
Its important to me that all configuration methods on these EZPlugGenerators are chainable. In other words, the methods used in setting up the synthesis graph should always return a pointer to the parent object. That allows me to use a syntax which very nicely shows the nested nature of the object relationships like this:
mixer.addGenerator(
a(new Panner())
->setVolume(0.1)
->setSource(
a(new TriggererPeriodic())
->setFrequency(
v(new FixedValue(1), "envTriggerFreq")
)
->setTriggerable(
a(new Enveloper())
->setAllTimes(v(0.0001), v(0.05), v(0.0f, "envSustain"), v(0.01))
->setAudioSource(
a(new SineWaveMod())
->setFrequency(
a(new Adder())
->addGenerator(a(new Adder()))
->addGenerator(v(5000, "sineFreq"))
->addGenerator(
a(new Multiplier())
->addVal(v("sineFreq"))
->addVal(
a(new TriggererPeriodic())
->setFrequency(v("envTriggerFreq"))
->setTriggerable(
a(new Enveloper())
->setAllTimes(0.1, 0.1, 0, 0.0001)
->setAudioSource(v(1, "envAmount"))
)
)
)
)
)
)
)
);
The "a" and "v" functions in the above code store and return references to objects and handle retrieving them and destroying them.
I suspect my approach to C++ looks a little weird, but I'm finding that the language can actually accommodate the way I want to program fairly well.
Now to my question
I'd like to create a common superclass for all EZPlugGenerators which can accept inputs to inherit from. This superclass would have a method, "addInput", which would be overridden by each subclass. The problem comes from the fact that I want "addInput" to return a pointer to an instance of the subclass, not the superclass.
This isn't acceptable:
EZPlugProcessor* addInput(EZPlugGenerator* generator)
because that returns a pointer to an instance of the superclass, not the sublass destroying the chainability that I'm so happy with.
I tried this:
template<typename T> virtual T* addInput(EZPlugGenerator* obj){
but the compiler tells me I can't create a virtual template function.
I don't HAVE to use inheritance here. I can implement 'addInput' on every single EZPlugGenerator that can take an input. It just seems like gathering all of them under a single parent class will help make it clear that they all have something in common, and will help enforce the fact that addInputis the proper way to plug one object in to another.
So, is there a way I can use inheritance to dictate that every member of a group of classes must implement an 'addInput' method, while allowing that method to return a pointer to an instance of the child class?
Virtual functions in C++ can have covariant return types, which means that you can define
virtual EZPlugProcessor *addInput(EZPlugGenerator* generator) = 0;
in the base class, and then
struct MyProcessor : EZPlugProcessor {
virtual MyProcessor *addinput(EZPlugGenerator* generator) {
...
return this;
}
};
As long as the caller knows (by the type they're using) that the object is a MyProcessor, they can chain addInput together with other functions specific to MyProcessor.
If your inheritance hierarchy has more levels, then unfortunately you'll sometimes find yourself writing:
struct MySpecificProcessor : MyProcessor {
virtual MySpecificProcessor *addinput(EZPlugGenerator* generator) {
return static_cast<MySpecificProcessor*>(MyProcessor::addInput(generator));
}
};
because there's no way to specify in EZPlugProcessor that the return type of addInput is "pointer to the most-derived type of the object". Each derived class has to "activate" the covariance for itself.
Yes, C++ already provides for covariant return types.
class Base
{
public:
virtual Base* add() = 0 { return <some base ptr>; }
};
class Child : public Base
{
public:
virtual Child* add() { return <some child ptr>; }
};
On the other hand no one will ever be able to read your code so you might want to consider if there's an alternate way to set up the configuration than writing LISP chaining in C++.
I was not really sure how to formulate my question, but here is the puzzle I am trying to resolve:
if (config.a)
myObject = new Object<DummyInterface>();
else
myObject = new Object<RealInterface>();
so the task is to create a object with a dummy interface if it is specified in config, otherwise use real interface class.
How do I declare myObject then?
there are couple options, I could have Object class to derive from abstract class without templates: i.e.:
class Base
{
...
}
template <class T>
class Object : public Base
{
...
}
Then I could declare myObject as:
Base* myObject;
But here is the problem: what if my Object class declares a non virtual method:
template <class T>
class Object : public Base
{
public:
T getInterface() { return myInterface;}
private:
T myInterface;
}
I cannot call it like this:
myObject->getInterface()
and I cannot do dynamic cast, because I don't know the type until the runtime...
Any suggestions how to get around it? Maybe there is a another solution?
One way around is to use the visitor pattern. This way, your base class may implement a visit() method and your derived instances can override...
For example..
SomeComponent
{
template <typename T> // I'm being lazy here, but you should handle specific types
void handle(T& cInst)
{
// do something
}
};
class Base
{
public:
virtual void visit(SomeComponent& cComp) = 0;
};
template <class T>
class Object : public Base
{
public:
virtual void visit(SomeComponent& cComp)
{
cComp.handle(*this);
}
};
Now you can do this
SomeComponent c;
Base* obj = new Object<int>;
obj->visit(c);
And c will get the correct type.
if (config.a)
myObject = new Object<DummyInterface>();
else
myObject = new Object<RealInterface>();
This construction is incorrect in terms of the polymorphism.
Two template instantiations are two different classes. The best situation is when you have something like that:
template <class T> SomeClass: public SomeBaseClass
{
};
.........
SomeBaseClass* myObject;
But it brings you no profit.
The simplest and right solution is the virtual functions. The visitor pattern seems useful too.
I actually think that the visitor pattern would be misused here. Instead, this is a classic switch-on-types code smell that is best handled by polymorphism.
When you say "what if one derived class has an additional method to call", that is assuming a specific design. That is not a functional requirement. A functional requirement would be "what if one of the two objects created had to do behavior X during event Y". Why is this different? Because there are a number of ways to implement this that don't require more interface (though maybe more methods).
Let me show an example.
You have your factory
std::map<ConfigValue, Generator> objectFactory_;
That you've registered a bunch of generators for (probably in constructor of class)
RegisterGenerator(configValueA, DummyGenerator);
RegisterGenerator(configValueB, RealGenerator);
...
And at some point you want to create one of those objects.
shared_ptr<Base> GetConfigObject(ConfigFile config)
{
return objectFactory_[config.a]();
}
And then you want to use the object for handling an event, you can do
void ManagingClass::HandleEventA()
{
theBaseObjectReturned->HandleEventAThroughInterfaceObject(this);
}
Note how I passed a this pointer. This means if you have one object that doesn't want to do anything (like make that extra behavior call) that your managing class may provide, it doesn't need to use this.
Object<DummyInterface>::HandleEventAThroughInterfaceObject(ManagingClass *)
{
// just do dummy behavior
}
And then if you want to do something extra (call a new behavior) it can do it through that pointer in the RealInterface
Object<RealInterface>::HandleEventAThroughInterfaceObject(ManagingClass * that)
{
that->DoExtraBehavior();
// then dummy - or whatever order
// you could even call multiple methods as needed
}
That's the basic approach you should always take when dealing with polymorphism. You should never have two different code paths for different types except through calls to virtual dispatch. You should never have two different code blocks, one that calls methods A, B, and C and another that only calls A and D when dealing with a base object, depending on type. Instead, always make the derived objects do the work of figuring out what to do - because they know who they are. If you need to do stuff in the managing object, pass a this pointer for them to work with.
is it possible to return exemplar of object using passed type name (string) in c++?
I have some base abstract class Base and a few derivates. Example code:
class Base
{
/* ... */
};
class Der1 : public Base
{
/* ... */
};
class Der2 : public Base
{
/* ... */
};
And I need function like:
Base *objectByType(const std::string &name);
Number of derivates classes are changeable and I don't want to make something like switching of name and returning by hands new object type. Is it possible in c++ to do that automatically anyway?
p.s. usage should looks like:
dynamic_cast<Der1>(objectByType("Der1"));
I need pure c++ code (crossplatform). Using boost is permissible.
There is a nice trick which allows you to write a factory method without a sequence of if...else if....
(note that, AFAIK, it is indeed not possible to do what you want in C++ as this code is generated in the compile time. A "Factory Method" Design Pattern exists for this purpose)
First, you define a global repository for your derived classes. It can be in the form std::map<std::string, Base*>, i.e. maps a name of the derived class to an instance of that class.
For each derived class you define a default constructor which adds an object of that class to the repository under class's name. You also define a static instance of the class:
// file: der1.h
#include "repository.h"
class Der1: public Base {
public:
Der1() { repository[std::string("Der1")] = this; }
};
// file: der1.cpp
static Der1 der1Initializer;
Constructors of static variables are run even before main(), so when your main starts you already have the repository initialized with instances of all derived classes.
Your factory method (e.g. Base::getObject(const std::string&)) needs to search the repository map for the class name. It then uses the clone() method of the object it finds to get a new object of the same type. You of course need to implement clone for each subclass.
The advantage of this approach is that when you are adding a new derived class your additions are restricted only to the file(s) implementing the new class. The repository and the factory code will not change. You will still need to recompile your program, of course.
It's not possible to do this in C++.
One options is to write a factory and switch on the name passed in, but I see you don't want to do that. C++ doesn't provide any real runtime reflection support beyond dynamic_cast, so this type of problem is tough to solve.
Yes that is possible! Check this very funny class called Activator
You can create everything by Type and string and can even give a List of parameters, so the method will call the appropriate constructor with the best set of arguments.
Unless I misunderstood, the typeid keyword should be a part of what you are looking for.
It is not possible. You have to write the objectByType function yourself:
Base* objectByType(const std::string& name) {
if (name == "Der1")
return new Der1;
else if (name == "Der2")
return new Der2;
// other possible tests
throw std::invalid_argument("Unknown type name " + name);
}
C++ doesn't support reflection.
In my opinion this is the single point where Java beats C++.
(ope not to get too many down votes for this...)
You could achieve something like that by using a custom preprocessor, similar to how MOC does for Qt.