Is it possible in C++ to overload in the child classes an overrided method?
I'm asking this because I have many child classes that although they are the same (in my case game objects) they interact in different ways with each others.
So, I need to create a function like void processCollision(GameObject obj) in the superclass.
But that could be overloaded in the child classes depending on the class of the GameObject (if it's a building, a car ...).
I'm just trying to run from the alternative which is using upcasting and RTTI.
What you're trying to implement is normally called "multiple dispatch" and unfortunately C++ doesn't support it directly (because in C++ view methods are bounded with classes and there are no multimethods).
Any C++ solution will require some coding for the implementation.
One simple symmetric way to implement it is to create a map for the supported cases:
typedef void (*Handler)(Obj *a, Obj *b);
typedef std::map<std::pair<OType, OType>, Handler> HandlerMap;
HandlerMap collision_handlers;
then the collision handling is:
HandlerMap::iterator i =
collision_handlers.find(std::make_pair(a->type, b->type));
if (i != collision_handlers.end()) i->second(a, b);
and the code goes in a free function.
If speed is a key factor and the object type can be coded in a small integer (e.g. 0...255) the dispatch could become for example:
collision_handlers[(a->type<<8)+b->type](a, b);
where collision handler is just an array of function pointers, and the speed should be equivalent to a single virtual dispatch.
The wikipedia link at the start of the answer lists another more sophisticated option for C++ (the visitor pattern).
"I'm just trying to run from the alternative which is using upcasting and RTTI."
Virtual polymorphism doesn't need upcasting or RTTI. Usually that's what virtual member functions are for:
class GameObject {
public:
virtual void processCollision(GameObject& obj);
};
class SomeGameObject1 : public GameObject {
public:
// SomeGameObject1's version of processCollision()
virtual void processCollision(GameObject& obj) {
// e.g here we also call the base class implementation
GameObject::processCollision();
// ... and add some additional operations
}
};
class SomeGameObject2 : public GameObject {
public:
// SomeGameObject2's version of processCollision()
virtual void processCollision(GameObject& obj) {
// Here we leave the base class implementation aside and do something
// completely different ...
}
};
MORE ADDITIONS AND THOUGHTS
As you're mentioning upcasting I'd suspect you want to handle collisions differently, depending on the actual GameObject type passed. This indeed would require upcasting (and thus RTTI) like follows
class Building : public GameObject {
public:
virtual void processCollision(GameObject& obj) {
Car* car = dynamic_cast<Car*>(&obj);
Airplane* airplane = dynamic_cast<Airplane*>(&obj);
if(car) {
car->crash();
}
else if(airplane) {
airplane->crash();
collapse();
}
void collapse();
};
Based on the above, that makes me contemplative about some design/architectural principles:
May be it's not the best idea to place the processCollision() implementation strategy to the GameObject classes themselves. These shouldn't know about each other (otherwise it will be tedious to introduce new GameObject types to the model)
You should introduce a kind of GameManager class that keeps track of moving/colliding GameObject instances, and chooses a GameObjectCollisionStrategy class implementing void processCollision(GameObject& a,GameObject& b); based on the actual types of a and b.
For choosing the strategy, and resolve the final GameObject implementations and corresponding strategies, you should concentrate all of that business knowdlege to a CollisionStrategyFactory, and delegate to this.
The latter would look something like this
class GameObjectCollisionStrategy {
public:
virtual processCollision(GameObject& a,GameObject& b) const = 0;
};
class CollideBuildingWithAirplane : public GameObjectCollisionStrategy {
public:
virtual void processCollision(GameObject& a,GameObject& b) const {
Building* building = dynamic_cast<Building*>(a);
Airplane* airplane = dynamic_cast<Airplane*>(b);
if(building && airplane) {
airplane->crash();
building->collapse();
}
}
};
class CollideBuildingWithCar : public GameObjectCollisionStrategy {
public:
virtual void processCollision(GameObject& a,GameObject& b) const {
Building* building = dynamic_cast<Building*>(a);
Car* car = dynamic_cast<Car*>(b);
if(building && car) {
car->crash();
}
}
};
class CollisionStrategyFactory {
public:
static const GameObjectCollisionStrategy& chooseStrategy
(GameObject* a, GameObject* b) {
if(dynamic_cast<Building*>(a)) {
if(dynamic_cast<Airplane*>(b)) {
return buildingAirplaneCollision;
}
else if(dynamic_cast<Car*>(b)) {
return buildingCarCollision;
}
}
return defaultCollisionStrategy;
}
private:
class DefaultCollisionStrategy : public GameObjectCollisionStrategy {
public:
virtual void processCollision(GameObject& a,GameObject& b) const {
// Do nothing.
}
};
// Known strategies
static CollideBuildingWithAirplane buildingAirplaneCollision;
static CollideBuildingWithCar buildingCarCollision;
static DefaultCollisionStrategy defaultCollisionStrategy;
};
class GameManager {
public:
void processFrame(std::vector<GameObject*> gameObjects) {
for(std::vector<GameObject*>::iterator it1 = gameObjects.begin();
it1 != gameObjects.end();
++it1) {
for(std::vector<GameObject*>::iterator it2 = gameObjects.begin();
it2 != gameObjects.end();
++it2) {
if(*it1 == *it2) continue;
if(*it1->collides(*it2)) {
const GameObjectCollisionStrategy& strategy =
CollisionStrategyFactory::chooseStrategy(*it1,*it2);
strategy->processCollision(*(*it1),*(*it2));
}
}
}
}
};
Alternatively you may want to opt for static polymorphism, which also works without RTTI, but needs all types known at compile time. The basic pattern is the so called CRTP.
That should look as follows
class GameObject {
public:
// Put all the common attributes here
const Point& position() const;
const Area& area() const;
void move(const Vector& value);
};
template<class Derived>
class GameObjectBase : public GameObject {
public:
void processCollision(GameObject obj) {
static_cast<Derived*>(this)->processCollisionImpl(obj);
}
};
class SomeGameObject1 : public GameObjectBase<SomeGameObject1 > {
public:
// SomeGameObject1's version of processCollisionImpl()
void processCollisionImpl(GameObject obj) {
}
};
class SomeGameObject2 : public GameObjectBase<SomeGameObject2 > {
public:
// SomeGameObject2's version of processCollisionImpl()
void processCollisionImpl(GameObject obj) {
}
};
But this would unnecessarily complicate the design, and I doubt it will provide any benefits for your use case.
Related
Here is the situation. Let's say we have a virtual base class (e.g. ShapeJuggler) which contains a method that takes a shared pointer to a virtual base class object (e.g. Shape) as argument. Let's jump into the following pseudo-code to understand:
class Shape {
}
class ShapeJuggler {
virtual void juggle(shared_ptr<Shape>) = 0;
}
// Now deriving a class from it
class Square : public Shape {
}
class SquareJuggler : public ShapeJuggler {
public:
void juggle(shared_ptr<Shape>) {
// Want to do something specific with a 'Square'
// Or transform the 'shared_ptr<Shape>' into a 'shared_ptr<Square>'
}
}
// Calling the juggle method
void main(void) {
shared_ptr<Square> square_ptr = (shared_ptr<Square>) new Square();
SquareJuggler squareJuggler;
squareJuggler.juggle(square_ptr); // how to access 'Square'-specific members?
}
make_shared or dynamic/static_cast don't seem to do the job.
Is it at all possible? Any ideas, suggestions?
Thanks
This is where std::dynamic_pointer_cast (or one of its friends) comes into play.
It's just like dynamic_cast, but for std::shared_ptrs.
In your case (assuming the Shape class is polymorphic so dynamic_cast works):
void juggle(shared_ptr<Shape> shape) {
auto const sq = std::dynamic_pointer_cast<Square>(shape);
assert(sq);
sq->squareSpecificStuff();
}
This is the multiple dispatch problem. Their are many solution to this problem, the cleanest might be using the visitor pattern, but if you just have one function that need multiple dispatch you could avoid using a visitor:
class SquareJuggler;
class TriangleJuggler;
//.... others concrete jugglers.
class Shape {
//The default behaviour for any juggler and any shape
virtual void juggle_by(Juggler& t) {
//default code for any shape an juggle
}
// list each juggler for which you may
// implement a specific behavior
virtual void juggle_by(SquareJuggler& t) {
//provides default behavior in case you will not
// create a specific behavior for a specific shape.
//for example, just call the unspecific juggler:
this->Shape::juggle_by(static_cast<Juggler&>(t));
}
virtual void juggle_by(TriangleJuggler& t) {
//provides default behavior in case you will not
//create a specific behavior for a specific shape.
//for example, just call the unspecific juggler:
this->Shape::juggle_by(static_cast<Juggler&>(t));
}
//...
};
// Now deriving a class from it
class Square : public Shape {
void juggle_by(SquareJuggler& s) override{
//code specific to SquareJuggler and Shape
}
};
class Triangle : public Shape {
void juggle_by(TriangleJuggler& t) override{
//code specific to TriangleJuggler and Shape
}
};
class ShapeJuggler {
virtual void juggle(shared_ptr<Shape> s) {
//by default (if default has sense):
s->juggle_by(*this);
}
};
class SquareJuggler: public ShapeJuggler {
public:
void juggle(shared_ptr<Shape> s) override {
s->juggle_by(*this);
}
};
class TriangleJuggler: public ShapeJuggler {
public:
void juggle(shared_ptr<Shape> s) override {
s->juggle_by(*this);
}
};
// Calling the juggle method
void main(void) {
shared_ptr<Square> square_ptr = (shared_ptr<Square>) new Square();
SquareJuggler squareJuggler;
squareJuggler.juggle(square_ptr);
//This last call, will perform two virtual calls:
// 1. SquareJuggler::juggle(shared_ptr<Shape);
// 2. Square::juggle_by(SquareJuggler&);
}
You could also defines your XXXJuggler as final, which will enable some devirtualization optimization.
I have a question regarding a design in C++.
As you see in the code below there is a design problem. I want to be able to have a TestClass which inherits from zero or more classes derived from ModeBase (ModeOne and ModeTwo in this example). If TestClass inherits from ModeOne, it would have the ability to use MethodeOne(), and it would be a requirement for TestClass to implement MethodOne() which is what I want.
class ModeBase
{
//--Methods--------------------------------------------------------------------
public:
virtual ~ModeBase() = default;
};
class ModeOne : private ModeBase
{
//--Methods--------------------------------------------------------------------
public:
virtual ~ModeOne() = default;
virtual void MethodOne() {}
};
class ModeTwo : private ModeBase
{
//--Methods--------------------------------------------------------------------
public:
virtual ~ModeTwo() = default;
virtual void MethodTwo() {}
};
class TestBase
{
//--Methods--------------------------------------------------------------------
public:
TestBase() : currentMode_( nullptr ) {}
virtual ~TestBase() = default;
template <class Mode, class T>
void ChangeMode()
{
if( std::is_base_of<Mode, T>::value )
{
// Class does inherit from Mode so we make sure the current mode
// has changed
currentMode_ = std::make_shared<Mode>();
}
else
{
// Class does not inherit from Mode so we don't do anything
}
}
template <class Mode>
bool CurrentMode()
{
if( std::dynamic_pointer_cast<Mode>(currentMode_) != nullptr )
{
return true;
}
return false;
}
//--Data members---------------------------------------------------------------
private:
std::shared_ptr<ModeBase> currentMode_;
};
class TestOne
: public TestBase
, private ModeOne
, private ModeTwo
{
//--Methods--------------------------------------------------------------------
~TestOne() = default;
void HeartbeatTick()
{
if( CurrentMode<ModeOne>() )
{
MethodOne();
}
else if( CurrentMode<ModeTwo>() )
{
MethodTwo();
}
}
virtual void MethodOne() {}
virtual void MethodTwo() {}
};
class SomeManager
{
~SomeManager() = default;
void ChangeAllMode()
{
for( auto it = vector_.begin(); it != vector_.end(); ++it )
{
// Here is the problem with this implementation. I need to know
// the type of the TestBase derived class (TestOne) to use it as
// a `ChangeMode` method template parameter.
//(*it)->ChangeMode<AIModeFollowLine, SOMETYPE>();
}
};
std::vector<std::shared_ptr<TestBase>> vector_;
};
I already know this is bad design since vector_ will be filled at runtime so I have no way of using ChangeMode like that. It appears that it would be a good solution to use multimethods, wouldn't it ? If so, what would the design look like ?
Multimethods (AKA multiple dispatch) deals with the issue of dispatching a call to a single function based on the runtime type of the parameters involved. This does not appear to be your issue (or have I misunderstood you?), as you have two different method names, implemented on two different types.
Your goal appears to be to select a method implementation based on a runtime type that you have injected into a class. It is not clear whether you are able to dictate the form which that injection takes but if you are then why do you not directly inject the implementation? Then you could use an implicit interface rather than an explicit one. In other words why not inject a functor-like object?
class TestBase
{
public:
typedef std::function<void ()> Ticker;
TestBase(Ticker hbTicker) : ticker{hbTicker} {}
void HeartbeatTick() {
ticker();
}
void setTicker(Ticker hbTicker){
ticker = hbTicker;
}
private:
Ticker ticker;
};
Seems like a lot less complicated to me if that meets your requirements.
If you really do need to implement multiple dispatch you will probably need to implement a visitor pattern on each of the parameters whose runtime type you need to determine. Not sure if that would work for multiple parameters though (I've not tried multiple parameters myself at least). Or you could use RTTI and a case statement or something like that.
I am just being stupid here !
I just have to use a different ChangeMode() method in order to know if TestBase and thus TestOne is of type ModeBase:
template<typename Mode>
bool
IsSame( TestBase* base )
{
return dynamic_cast<Mode*>(base) != nullptr;
};
template <class Mode>
void
ChangeMode()
{
if( isSame<Mode>(this) )
{
// Change the ticker method
}
else
{
}
}
BIG EDIT
So after gathering some feedback from all of you, and meditating on the XY problem as Zack suggested, I decided to add another code example which illustrates exactly what I'm trying to accomplish (ie the "X") instead of asking about my "Y".
So now we are working with cars and I've added 5 abstract classes: ICar, ICarFeatures, ICarParts, ICarMaker, ICarFixer. All of these interfaces will wrap or use a technology-specific complex object provided by a 3rd party library, depending on the derived class behind the interface. These interfaces will intelligently manage the life cycle of the complex library objects.
My use case here is the FordCar class. In this example, I used the Ford library to access classes FordFeatureImpl, FordPartsImpl, and FordCarImpl. Here is the code:
class ICar {
public:
ICar(void) {}
virtual ~ICar(void) {}
};
class FordCar : public ICar {
public:
ICar(void) {}
~FordCar(void) {}
FordCarImpl* _carImpl;
};
class ICarFeatures {
public:
ICarFeatures(void) {}
virtual ~ICarFeatures(void) {}
virtual void addFeature(UserInput feature) = 0;
};
class FordCarFeatures : public ICarFeatures{
public:
FordCarFeatures(void) {}
virtual ~FordCarFeatures(void) {}
virtual void addFeature(UserInput feature){
//extract useful information out of feature, ie:
std::string name = feature.name;
int value = feature.value;
_fordFeature->specialAddFeatureMethod(name, value);
}
FordFeatureImpl* _fordFeature;
};
class ICarParts {
public:
ICarParts(void) {}
virtual ~ICarParts(void) {}
virtual void addPart(UserInput part) = 0;
};
class FordCarParts :public ICarParts{
public:
FordCarParts(void) {}
virtual ~FordCarParts(void) {}
virtual void addPart(UserInput part) {
//extract useful information out of part, ie:
std::string name = part.name;
std::string dimensions = part.dimensions;
_fordParts->specialAddPartMethod(name, dimensions);
}
FordPartsImpl* _fordParts;
};
class ICarMaker {
public:
ICarMaker(void) {}
virtual ~ICarMaker(void) {}
virtual ICar* makeCar(ICarFeatures* features, ICarParts* parts) = 0;
};
class FordCarMaker {
public:
FordCarMaker(void) {}
virtual ~FordCarMaker(void) {}
virtual ICar* makeCar(ICarFeatures* features, ICarParts* parts){
FordFeatureImpl* fordFeatures = dynamic_cast<FordFeatureImpl*>(features);
FordPartsImpl* fordParts = dynamic_cast<FordPartsImpl*>(parts);
FordCar* fordCar = customFordMakerFunction(fordFeatures, fordParts);
return dynamic_cast<ICar*>(fordCar);
}
FordCar* customFordMakerFunction(FordFeatureImpl* fordFeatures, FordPartsImpl* fordParts) {
FordCar* fordCar = new FordCar;
fordCar->_carImpl->specialFeatureMethod(fordFeatures);
fordCar->_carImpl->specialPartsMethod(fordParts);
return fordCar;
}
};
class ICarFixer {
public:
ICarFixer(void) {}
virtual ~ICarFixer(void) {}
virtual void fixCar(ICar* car, ICarParts* parts) = 0;
};
class FordCarFixer {
public:
FordCarFixer(void) {}
virtual ~FordCarFixer(void) {}
virtual void fixCar(ICar* car, ICarParts* parts) {
FordCar* fordCar = dynamic_cast<FordCar*>(car);
FordPartsImpl* fordParts = dynamic_cast<FordPartsImpl*>(parts);
customFordFixerFunction(fordCar, fordParts);
}
customFordFixerFunction(FordCar* fordCar, FordPartsImpl* fordParts){
fordCar->_carImpl->specialRepairMethod(fordParts);
}
};
Notice that I must use dynamic casting to access the technology-specific objects within the abstract interfaces. This is what makes me think I'm abusing inheritance and provoked me to ask this question originally.
Here is my ultimate goal:
UserInput userInput = getUserInput(); //just a configuration file ie XML/YAML
CarType carType = userInput.getCarType();
ICarParts* carParts = CarPartFactory::makeFrom(carType);
carParts->addPart(userInput);
ICarFeatures* carFeatures = CarFeaturesFactory::makeFrom(carType);
carFeatures->addFeature(userInput);
ICarMaker* carMaker = CarMakerFactory::makeFrom(carType);
ICar* car = carMaker->makeCar(carFeatures, carParts);
UserInput repairSpecs = getUserInput();
ICarParts* replacementParts = CarPartFactory::makeFrom(carType);
replacementParts->addPart(repairSpecs);
ICarFixer* carFixer = CarFixerFactory::makeFrom(carType);
carFixer->fixCar(car, replacementParts);
Perhaps now you all have a better understanding of what I'm trying to do and perhaps where I can improve.
I'm trying to use pointers of base classes to represent derived (ie Ford) classes, but the derived classes contain specific objects (ie FordPartsImpl) which are required by the other derived classes (ie FordCarFixer needs a FordCar and FordPartsImpl object). This requires me to use dynamic casting to downcast a pointer from the base to its respective derived class so I can access these specific Ford objects.
My question is: am I abusing inheritance here? I'm trying to have a many-to-many relationship between the workers and objects. I feel like I'm doing something wrong by having an Object family of class which literally do nothing but hold data and making the ObjectWorker class have to dynamic_cast the object to access the insides.
That is not abusing inheritance... This is abusing inheritance
class CSNode:public CNode, public IMvcSubject, public CBaseLink,
public CBaseVarObserver,public CBaseDataExchange, public CBaseVarOwner
Of which those who have a C prefix have huge implementations
Not only that... the Header is over 300 lines of declarations.
So no... you are not abusing inheritance right now.
But this class I just showed you is the product of erosion. I'm sure the Node as it began it was a shinning beacon of light and polymorphism, able to switch smartly between behavior and nodes.
Now it has become a Kraken, a Megamoth, Cthulu itself trying to chew my insides with only a vision of it.
Heed this free man, heed my counsel, beware of what your polymorphism may become.
Otherwise it is fine, a fine use of inheritance of something I suppose is an Architecture in diapers.
What other alternatives do I have if I want to only have a single work() method?
Single Work Method... You could try:
Policy Based Design, where a policy has the implementation of your model
A Function "work" that it is used by every single class
A Functor! Instantiated in every class that it will be used
But your inheritance seems right, a single method that everyone will be using.
One more thing....I'm just gonna leave this wiki link right here
Or maybe just copy paste the wiki C++ code... which is very similar to yours:
#include <iostream>
#include <string>
template <typename OutputPolicy, typename LanguagePolicy>
class HelloWorld : private OutputPolicy, private LanguagePolicy
{
using OutputPolicy::print;
using LanguagePolicy::message;
public:
// Behaviour method
void run() const
{
// Two policy methods
print(message());
}
};
class OutputPolicyWriteToCout
{
protected:
template<typename MessageType>
void print(MessageType const &message) const
{
std::cout << message << std::endl;
}
};
class LanguagePolicyEnglish
{
protected:
std::string message() const
{
return "Hello, World!";
}
};
class LanguagePolicyGerman
{
protected:
std::string message() const
{
return "Hallo Welt!";
}
};
int main()
{
/* Example 1 */
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish> HelloWorldEnglish;
HelloWorldEnglish hello_world;
hello_world.run(); // prints "Hello, World!"
/* Example 2
* Does the same, but uses another language policy */
typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman> HelloWorldGerman;
HelloWorldGerman hello_world2;
hello_world2.run(); // prints "Hallo Welt!"
}
More important questions are
How are you going to use an Int Object with your StringWorker?
You current implementation won't be able to handle that
With policies it is possible.
What are the possible objects?
Helps you define if you need this kind of behavior
And remember, don't kill a chicken with a shotgun
Maybe your model will never really change overtime.
You have committed a design error, but it is not "abuse of inheritance". Your error is that you are trying to be too generic. Meditate upon the principle of You Aren't Gonna Need It. Then, think about what you actually have. You don't have Objects, you have Dogs, Cats, and Horses. Or perhaps you have Squares, Polygons, and Lines. Or TextInEnglish and TextInArabic. Or ... the point is, you probably have a relatively small number of concrete things and they probably all go in the same superordinate category. Similarly, you do not have Workers. On the assumption that what you have is Dogs, Cats, and Horses, then you probably also have an Exerciser and a Groomer and a Veterinarian.
Think about your concrete problem in concrete terms. Implement only the classes and only the relationships that you actually need.
The point is that you're not accessing the specific functionality through the interfaces. The whole reason for using interfaces is that you want all Cars to be made, fixed and featured ... If you're not going to use them in that way, don't use interfaces (and inheritance) at all, but simply check at user input time which car was chosen and instantiate the correct specialized objects.
I've changed your code a bit so that only at "car making" time there will be an upward dynamic_cast. I would have to know all the things you want to do exactly to create interfaces I would be really happy with.
class ICar {
public:
ICar(void) {}
virtual ~ICar(void) {}
virtual void specialFeatureMethod(ICarFeatures *specialFeatures);
virtual void specialPartsMethod(ICarParts *specialParts);
virtual void specialRepairMethod(ICarParts *specialParts);
};
class FordCar : public ICar {
public:
FordCar(void) {}
~FordCar(void) {}
void specialFeatureMethod(ICarFeatures *specialFeatures) {
//Access the specialFeatures through the interface
//Do your specific Ford stuff
}
void specialPartsMethod(ICarParts *specialParts) {
//Access the specialParts through the interface
//Do your specific Ford stuff
}
void specialRepairMethod(ICarParts *specialParts) {
//Access the specialParts through the interface
//Do your specific Ford stuff
}
};
class ICarFeatures {
public:
ICarFeatures(void) {}
virtual ~ICarFeatures(void) {}
virtual void addFeature(UserInput feature) = 0;
};
class FordCarFeatures : public ICarFeatures{
public:
FordCarFeatures(void) {}
~FordCarFeatures(void) {}
void addFeature(UserInput feature){
//extract useful information out of feature, ie:
std::string name = feature.name;
int value = feature.value;
_fordFeature->specialAddFeatureMethod(name, value);
}
FordFeatureImpl* _fordFeature;
};
class ICarParts {
public:
ICarParts(void) {}
virtual ~ICarParts(void) {}
virtual void addPart(UserInput part) = 0;
};
class FordCarParts :public ICarParts{
public:
FordCarParts(void) {}
~FordCarParts(void) {}
void addPart(UserInput part) {
//extract useful information out of part, ie:
std::string name = part.name;
std::string dimensions = part.dimensions;
_fordParts->specialAddPartMethod(name, dimensions);
}
FordPartsImpl* _fordParts;
};
class ICarMaker {
public:
ICarMaker(void) {}
virtual ~ICarMaker(void) {}
virtual ICar* makeCar(ICarFeatures* features, ICarParts* parts) = 0;
};
class FordCarMaker {
public:
FordCarMaker(void) {}
~FordCarMaker(void) {}
ICar* makeCar(ICarFeatures* features, ICarParts* parts){
return customFordMakerFunction(features, parts);
}
ICar* customFordMakerFunction(ICarFeatures* features, ICarParts* parts) {
FordCar* fordCar = new FordCar;
fordCar->specialFeatureMethod(features);
fordCar->specialPartsMethod(parts);
return dynamic_cast<ICar*>(fordCar);
}
};
class ICarFixer {
public:
ICarFixer(void) {}
virtual ~ICarFixer(void) {}
virtual void fixCar(ICar* car, ICarParts* parts) = 0;
};
class FordCarFixer {
public:
FordCarFixer(void) {}
~FordCarFixer(void) {}
void fixCar(ICar* car, ICarParts* parts) {
customFordFixerFunction(car, parts);
}
void customFordFixerFunction(ICar* fordCar, ICarParts *fordParts){
fordCar->specialRepairMethod(fordParts);
}
};
One can do better (for certain values of "better"), with increased complexity.
What is actually being done here? Let's look point by point:
There's some object type, unknown statically, determined at run time from a string
There's some worker type, also unknown statically, determined at run time from another string
Hopefully the object type and the worker type will match
We can try to turn "hopefully" into "certainly" with some template code.
ObjectWorkerDispatcher* owd =
myDispatcherFactory->create("someWorker", "someObject");
owd->dispatch();
Obviously both object and worker are hidden in the dispatcher, which is completely generic:
class ObjectWorkerDispatcher {
ObjectWorkerDispatcher(string objectType, string workerType) { ... }
virtual void dispatch() = 0;
}
template <typename ObjectType>
class ConcreteObjectWorkerDispatcher : public ObjectWorkerDispatcher {
void dispatch () {
ObjectFactory<ObjectType>* of = findObjectFactory(objectTypeString);
WorkerFactory<ObjectType>* wf = findWorkerFactory(workerTypeString);
ObjectType* obj = of->create();
Worker<ObjectType>* wrk = wf->create();
wrk->doWork(obj);
}
map<string, ObjectFactory<ObjectType>*> objectFactories;
map<string, WorkerFactory<ObjectType>*> workerFactories;
ObjectFactory<ObjectType>* findObjectFactory(string) { .. use map }
WorkerFactory<ObjectType>* findWorkerFactory(string) { .. use map }
}
We have different unrelated types of Object. No common Object class, but we can have e.g. several subtypes of StringObject, all compatible with all kinds of StringWorker.
We have an abstract Worker<ObjectType> class template and concrete MyStringWorker : public Worker<StringObject> , OtherStringWorker : public Worker<StringObject> ... classes.
Both kinds of factories are inheritance-free. Different types of factories are kept completely separate (in different dispatchers) and never mix.
There's still some amount of blanks to fill in, but hopefully it all should be more or less clear.
No casts are used in making of this design. You decide whether this property alone is worth such an increase in complexity.
I think you have the right solution per your needs. One thing I see that can be improved is removing the use of carType from the function that deals with the objects at the base class level.
ICar* FordCarFixer::getFixedCar(UserInput& userInput)
{
FordCarParts* carParts = new FordPartFactory;
carParts->addPart(userInput);
FordCarFeatures* carFeatures = new FordCarFeatures;
carFeatures->addFeature(userInput);
FordCarMaker* carMaker = new FordCarMaker;
FordCar* car = carMaker->makeCar(carFeatures, carParts);
UserInput repairSpecs = getUserInput();
ForCarParts* replacementParts = new ForCarParts;
replacementParts->addPart(repairSpecs);
FordCarFixer* carFixer = new FordCarFixer;
carFixer->fixCar(car, replacementParts);
return car;
}
UserInput userInput = getUserInput();
ICar* car = CarFixerFactory::getFixedCar(userInput);
With this approach, most of the objects at FordCarFixer level are Ford-specific.
I want to create a class factory and I would like to use reflection for that. I just need to
create a object with given string and invoke only few known methods.
How i can do that?
You will have to roll your own. Usually you have a map of strings to object creation functions.
You will need something like the follwing:
class thing {...};
/*
class thing_A : public thing {...};
class thing_B : public thing {...};
class thing_C : public thing {...};
*/
std::shared_ptr<thing> create_thing_A();
std::shared_ptr<thing> create_thing_C();
std::shared_ptr<thing> create_thing_D();
namespace {
typedef std::shared_ptr<thing> (*create_func)();
typedef std::map<std::string,create_func> creation_map;
typedef creation_map::value_type creation_map_entry;
const creation_map_entry creation_map_entries[] = { {"A", create_thing_A}
, {"B", create_thing_B}
, {"C", create_thing_C} };
const creation_map creation_funcs(
creation_map_entries,
creation_map_entries + sizeof(creation_map_entries)
/ sizeof(creation_map_entries[0] );
}
std::shared_ptr<thing> create_thing(const std::string& type)
{
const creation_ma::const_iterator it = creation_map.find(type);
if( it == creation_map.end() ) {
throw "Dooh!"; // or return NULL or whatever suits you
}
return it->second();
}
There are other ways to do this (like having a map of strings to objects from which to clone), but I think they all boil down to having a map of strings to something related to the specific types.
There is no reflection in C++, directly supported by the standard.
However C++ is sufficiently low-level that you can implement some minimal support for reflection to complete the task at hand.
For the simple task of creating a Factory, you usually use the Prototype approach:
class Base
{
public:
virtual Base* clone() const = 0;
virtual ~Base();
};
class Factory
{
public:
std::unique_ptr<Base> get(std::string const& name);
void set(std::string const& name, std::unique_ptr<Base> b);
private:
boost::ptr_map<std::string,Base> mExemplars;
};
Of course, those "known methods" that you are speaking about should be defined within the Base class, which acts as an interface.
There is no reflection in C++, so you should restate your question trying to explain what are the requirements that you would have fulfilled with the reflection part of it.
Depending on your actual constraints and requirements, there are a few things that you can do. The first approach that I would take would be creating an abstract factory where concrete factories can register and provide a simple interface:
class Base {}; // shared base by all created objects
class ConcreteFactoryBase {
public:
virtual ~ConcreteFactoryBase() {}
virtual Base* create() const = 0; // actual construction
virtual std::string id() const = 0; // id of the types returned
};
class AbstractFactory
{
typedef std::map<std::string, ConcreteFactory* > factory_map_t;
public:
void registerFactory( ConcreteFactoryBase* factory ) {
factories[ factory->id() ] = factory;
}
Base* create( std::string const & id ) const {
factory_map_t::const_iterator it = factories.find( id );
if ( it == factories.end() ) {
return 0; // or throw, or whatever makes sense in your case
}
return (*it)->create();
}
~AbstractFactory(); // ensure that the concrete factories are deleted
private:
std::map<ConcreteFactoryBase*> factories;
};
The actual concrete factories can be implemented manually but they can probably be templated, unless the constructors for the different types require different arguments:
template <typename T>
class ConcreteFactory : public ConcreteFactoryBase {
public:
ConcreteFactory( std::string const & id ) : myid(id) {}
virtual Base* create() const {
return new T;
}
virtual std::string id() const {
return myid;
}
private:
std::string myid;
};
class Test : public Base {};
int main() {
AbstracFactory factory;
factory.register_factory( new ConcreteFactory<Test>("Test") );
}
Optionally you could adapt the signatures so that you can pass arguments to the constructor through the different layers.
Then again, by knowing the actual constraints some other approaches might be better. The clone() approach suggested elsewhere is good (either by actually cloning or by creating an empty object of the same type). That is basically blending the factory with the objects themselves so that each object is a factory of objects of the same type. I don't quite like mixing those two responsabilities but it might be one of the simplest approaches with less code to write.
You could use typeid & templates to implement the factory so you won't need strings at all.
#include <string>
#include <map>
#include <typeinfo>
//***** Base *****
class Base
{
public:
virtual ~Base(){} //needs to be virtual to make typeid work
};
//***** C1 *****
class C1 : public Base
{};
//***** Factory *****
class Factory
{
public:
template <class T>
Base& get();
private:
typedef std::map<std::string, Base> BaseMap;
BaseMap m_Instances;
};
template <class T>
Base& Factory::get()
{
BaseMap::const_iterator i = m_Instances.find(typeid(T).name());
if(i == m_Instances.end()) {
m_Instances[typeid(T).name()] = T();
}
return m_Instances[typeid(T).name()];
}
//***** main *****
int main(int argc, char *argv[])
{
Factory f;
Base& c1 = f.get<C1>();
return 0;
}
I have this pimpl design where the implementation classes are polymorphic but the interfaces are supposed to just contain a pointer, making them polymorphic somewhat defeats the purpose of the design.
So I create my Impl and Intf base classes to provide reference counting. And then the user can create their implementations. An example:
class Impl {
mutable int _ref;
public:
Impl() : _ref(0) {}
virtual ~Impl() {}
int addRef() const { return ++_ref; }
int decRef() const { return --_ref; }
};
template <typename TImpl>
class Intf {
TImpl* impl;
public:
Intf(TImpl* t = 0) : impl(0) {}
Intf(const Intf& other) : impl(other.impl) { if (impl) impl->addRef(); }
Intf& operator=(const Intf& other) {
if (other.impl) other.impl->addRef();
if (impl && impl->decRef() <= 0) delete impl;
impl = other.impl;
}
~Intf() { if (impl && impl->decRef() <= 0) delete impl; }
protected:
TImpl* GetImpl() const { return impl; }
void SetImpl(... //etc
};
class ShapeImpl : public Impl {
public:
virtual void draw() = 0;
};
class Shape : public Intf<ShapeImpl> {
public:
Shape(ShapeImpl* i) : Intf<ShapeImpl>(i) {}
void draw() {
ShapeImpl* i = GetImpl();
if (i) i->draw();
}
};
class TriangleImpl : public ShapeImpl {
public:
void draw();
};
class PolygonImpl : public ShapeImpl {
public:
void draw();
void addSegment(Point a, Point b);
};
Here is where have the issue. There are two possible declaration for class Polygon:
class Polygon1 : public Intf<PolygonImpl> {
public:
void draw() {
PolygonImpl* i = GetImpl();
if (i) i->draw();
}
void addSegment(Point a, Point b) {
PolygonImpl* i = GetImpl();
if (i) i->addSegment(a,b);
}
};
class Polygon2 : public Shape {
void addSegment(Point a, Point b) {
ShapeImpl* i = GetImpl();
if (i) dynamic_cast<Polygon*>(i)->addSegment(a,b);
}
}
In the Polygon1, I have rewrite the code for draw because I have not inherited it. In Polygon2 I need ugly dynamic casts because GetImpl() doesn't know about PolygonImpl. What I would like to do is something like this:
template <typename TImpl>
struct Shape_Interface {
void draw() {
TImpl* i = GetImpl();
if (i) i->draw();
}
};
template <typename TImpl>
struct Polygon_Interface : public Shape_Interface<Timpl> {
void addSegment(Point a, Point b) { ... }
};
class Shape : public TIntf<ShapeImpl>, public Shape_Interface<ShapeImpl> {...};
class Polygon : public TIntf<PolygonImpl>, public Polygon_Interface<PolygonImpl> {
public:
Polygon(PolygonImpl* i) : TIntf<PolygonImpl>(i) {}
};
But of course there's a problem here. I can't access GetImpl() from the Interface classes unless I derive them from Intf. And if I do that, I need to make Intf virtual everywhere it appears.
template <typename TImpl>
class PolygonInterface : public virtual Intf<TImpl> { ... };
class Polygon : public virtual Intf<PolygonImpl>, public PolygonInterface { ... }
OR I can store a TImpl*& in each Interface and construct them with a reference to the base Intf::impl. But that just means I have a pointer pointing back into myself for every interface included.
template <typename TImpl>
class PolygonInterface {
TImpl*& impl;
public:
PolygonInterface(TImpl*& i) : impl(i) {}
...};
Both of these solutions bloat the Intf class, add an extra dereference, and basically provide no benefit over straight polymorphism.
So, the question is, is there a third way, that I've missed that would solve this issue besides just duplicating the code everywhere (with its maintenance issues)?
TOTALLY SHOULD, BUT DOESN'T WORK: I wish there were base classes unions that just overlaid the class layouts and, for polymorphic classes, required that they have the exact same vtable layout. Then both Intf and ShapeInterface would each declare a single T* element and access it identically:
class Shape : public union Intf<ShapeImpl>, public union ShapeInterface<ShapeImpl> {};
I should note that your Impl class is nothing more than the reimplementation of a shared_ptr without the thread safety and all those cast bonuses.
Pimpl is nothing but a technic to avoid needless compile-time dependencies.
You do not need to actually know how a class is implemented to inherit from it. It would defeat the purpose of encapsulation (though your compiler does...).
So... I think that you are not trying to use Pimpl here. I would rather think this is a kind of Proxy patterns, since apparently:
Polygon1 numberOne;
Polygon2 numberTwo = numberOne;
numberTwo.changeData(); // affects data from numberOne too
// since they point to the same pointer!!
If you want to hide implementation details
Use Pimpl, but the real one, it means copying in depth during copy construction and assignment rather than just passing the pointer around (whether ref-counted or not, though ref-counted is preferable of course :) ).
If you want a proxy class
Just use a plain shared_ptr.
For inheritance
It does not matter, when you inherit from a class, how its private members are implemented. So just inherit from it.
If you want to add some new private members (usual case), then:
struct DerivedImpl;
class Derived: public Base // Base implemented with a Pimpl
{
public:
private:
std::shared_ptr<DerivedImpl> _data;
};
There is not much difference with classic implementation, as you can see, just that there is a pointer in lieu of a bunch of data.
BEWARE
If you forward declare DerivedImpl (which is the goal of Pimpl), then the destructor automatically generated by the compiler is... wrong.
The problem is that in order to generate the code for the destructor, the compiler needs the definition of DerivedImpl (ie: a complete type) in order to know how to destroy it, since a call to delete is hidden in the bowels of shared_ptr. However it may only generate a warning at compilation time (but you'll have a memory leak).
Furthermore, if you want an in-depth copy (rather than a shallow one, which consists in the copy and the original both pointing to the same DerivedImpl instance), you will also have to define manually the copy-constructor AND the assignment operator.
You may decide to create a better class that shared_ptr which will have deep-copy semantics (which could be called member_ptr as in cryptopp, or just Pimpl ;) ). This introduce a subtle bug though: while the code generated for the copy-constructor and the assignement operator could be thought of as correct, they are not, since once again you need a complete type (and thus the definition of DerivedImpl), so you will have to write them manually.
This is painful... and I'm sorry for you.
EDIT: Let's have a Shape discussion.
// Shape.h
namespace detail { class ShapeImpl; }
class Shape
{
public:
virtual void draw(Board& ioBoard) const = 0;
private:
detail::ShapeImpl* m_impl;
}; // class Shape
// Rectangle.h
namespace detail { class RectangleImpl; }
class Rectangle: public Shape
{
public:
virtual void draw(Board& ioBoard) const;
size_t getWidth() const;
size_t getHeight() const;
private:
detail::RectangleImpl* m_impl;
}; // class Rectangle
// Circle.h
namespace detail { class CircleImpl; }
class Circle: public Shape
{
public:
virtual void draw(Board& ioBoard) const;
size_t getDiameter() const;
private:
detail::CircleImpl* m_impl;
}; // class Circle
You see: neither Circle nor Rectangle care if Shape uses Pimpl or not, as its name implies, Pimpl is an implementation detail, something private that is not shared with the descendants of the class.
And as I explained, both Circle and Rectangle use Pimpl too, each with their own 'implementation class' (which can be nothing more than a simple struct with no method by the way).
I think you were right in that I didn't understand your question initially.
I think you're trying to force a square shape into a round hole... it don't quite fit C++.
You can force that your container holds pointers to objects of a given base-layout, and then allow objects of arbitrary composition to be actually pointed to from there, assuming that you as a programmer only actually place objects that in fact have identical memory layouts (member-data - there's no such thing as member-function-layout for a class unless it has virtuals, which you wish to avoid).
std::vector< boost::shared_ptr<IShape> > shapes;
NOTE at the absolute MINIMUM, you must still have a virtual destructor defined in IShape, or object deletion is going to fail miserably
And you could have classes which all take a pointer to a common implementation core, so that all compositions can be initialized with the element that they share (or it could be done statically as a template via pointer - the shared data).
But the thing is, if I try to create an example, I fall flat the second I try to consider: what is the data shared by all shapes? I suppose you could have a vector of Points, which then could be as large or small as any shape required. But even so, Draw() is truly polymorphic, it isn't an implementation that can possibly be shared by multiple types - it has to be customized for various classifications of shapes. i.e. a circle and a polygon cannot possibly share the same Draw(). And without a vtable (or some other dynamic function pointer construct), you cannot vary the function called from some common implementation or client.
Your first set of code is full of confusing constructs. Maybe you can add a new, simplified example that PURELY shows - in a more realistic way - what you're trying to do (and ignore the fact that C++ doesn't have the mechanics you want - just demonstrate what your mechanic should look like).
To my mind, I just don't get the actual practical application, unless you're tyring to do something like the following:
Take a COM class, which inherits from two other COM Interfaces:
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser
{
...
};
And now I have a diamond inheritence pattern: IShellBrowser inherits ultimately from IUnknown, as does ICommDlgBrowser. But it seems incredibly silly to have to write my own IUnknown:AddRef and IUnknown::Release implementation, which is a highly standard implementation, because there's no way to cause the compiler to let another inherited class supply the missing virtual functions for IShellBrowser and/or ICommDlgBrowser.
i.e., I end up having to:
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser
{
public:
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++m_refcount; }
virtual ULONG STDMETHODCALLTYPE Release(void) { return --m_refcount; }
...
}
because there's no way I know of to "inherit" or "inject" those function implementations into MyShellBrowserDialog from anywhere else which actually fill-in the needed virtual member function for either IShellBrowser or ICommDlgBrowser.
I can, if the implementations were more complex, manually link up the vtable to an inherited implementor if I wished:
class IUnknownMixin
{
ULONG m_refcount;
protected:
IUnknonwMixin() : m_refcount(0) {}
ULONG AddRef(void) { return ++m_refcount; } // NOTE: not virutal
ULONG Release(void) { return --m_refcount; } // NOTE: not virutal
};
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser, private IUnknownMixin
{
public:
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return IUnknownMixin::AddRef(); }
virtual ULONG STDMETHODCALLTYPE Release(void) { return IUnknownMixin::Release(); }
...
}
And if I needed the mix-in to actually refer to the most-derived class to interact with it, I could add a template parameter to IUnknownMixin, to give it access to myself.
But what common elements could my class have or benefit by that IUnknownMixin couldn't itself supply?
What common elements could any composite class have that various mixins would want to have access to, which they needed to derive from themselves? Just have the mixins take a type parameter and access that. If its instance data in the most derived, then you have something like:
template <class T>
class IUnknownMixin
{
T & const m_outter;
protected:
IUnknonwMixin(T & outter) : m_outter(outter) {}
// note: T must have a member m_refcount
ULONG AddRef(void) { return ++m_outter.m_refcount; } // NOTE: not virtual
ULONG Release(void) { return --m_outter.m_refcount; } // NOTE: not virtual
};
Ultimately your question remains somewhat confusing to me. Perhaps you could create that example that shows your preferred-natural-syntax that accomplishes something clearly, as I just don't see that in your initial post, and I can't seem to sleuth it out from toying with these ideas myself.
I have seen lots of solutions to this basic conundrum: polymorphism + variation in interfaces.
One basic approach is to provide a way to query for extended interfaces - so you have something along the lines of COM programming under Windows:
const unsigned IType_IShape = 1;
class IShape
{
public:
virtual ~IShape() {} // ensure all subclasses are destroyed polymorphically!
virtual bool isa(unsigned type) const { return type == IType_IShape; }
virtual void Draw() = 0;
virtual void Erase() = 0;
virtual void GetBounds(std::pair<Point> & bounds) const = 0;
};
const unsigned IType_ISegmentedShape = 2;
class ISegmentedShape : public IShape
{
public:
virtual bool isa(unsigned type) const { return type == IType_ISegmentedShape || IShape::isa(type); }
virtual void AddSegment(const Point & a, const Point & b) = 0;
virtual unsigned GetSegmentCount() const = 0;
};
class Line : public IShape
{
public:
Line(std::pair<Point> extent) : extent(extent) { }
virtual void Draw();
virtual void Erase();
virtual void GetBounds(std::pair<Point> & bounds);
private:
std::pair<Point> extent;
};
class Polygon : public ISegmentedShape
{
public:
virtual void Draw();
virtual void Erase();
virtual void GetBounds(std::pair<Point> & bounds);
virtual void AddSegment(const Point & a, const Point & b);
virtual unsigned GetSegmentCount() const { return vertices.size(); }
private:
std::vector<Point> vertices;
};
Another option would be to make a single richer base interface class - which has all the interfaces you need, and then to simply define a default, no-op implementation for those in the base class, which returns false or throws to indicate that it isn't supported by the subclass in question (else the subclass would have provided a functional implementation for this member function).
class Shape
{
public:
struct Unsupported
{
Unsupported(const std::string & operation) : bad_op(operation) {}
const std::string & AsString() const { return bad_op; }
std::string bad_op;
};
virtual ~Shape() {} // ensure all subclasses are destroyed polymorphically!
virtual void Draw() = 0;
virtual void Erase() = 0;
virtual void GetBounds(std::pair<Point> & bounds) const = 0;
virtual void AddSegment(const Point & a, const Point & b) { throw Unsupported("AddSegment"); }
virtual unsigned GetSegmentCount() const { throw Unsupported("GetSegmentCount"); }
};
I hope that this helps you to see some possibilities.
Smalltalk had the wonderful attribute of being able to ask the meta-type-system whether a given instance supported a particular method - and it supported having a class-handler that could execute anytime a given instance was told to perform an operation it didn't support - along with what operation that was, so you could forward it as a proxy, or you could throw a different error, or simply quietly ignore that operation as a no-op).
Objective-C supports all of those same modalities as Smalltalk! Very, very cool things can be accomplished by having access to the type-system at runtime. I assume that .NET can pull of some crazy cool stuff along those lines (though I doubt that its nearly as elegant as Smalltalk or Objective-C, from what I've seen).
Anyway, ... good luck :)