Suppose I have a bunch of fruit:
class Fruit { ... };
class Apple : public Fruit { ... };
class Orange: public Fruit { ... };
And some polymorphic functions that operate on said fruit:
void Eat(Fruit* f, Pesticide* p) { ... }
void Eat(Apple* f, Pesticide* p) { ingest(f,p); }
void Eat(Orange* f, Pesticide* p) { peel(f,p); ingest(f,p); }
OK, wait. Stop right there. Note at this point that any sane person would make Eat() a virtual member function of the Fruit classes. But that's not an option, because I am not a sane person. Also, I don't want that Pesticide* in the header file for my fruit class.
Sadly, what I want to be able to do next is exactly what member functions and dynamic binding allow:
typedef list<Fruit*> Fruits;
Fruits fs;
...
for(Fruits::iterator i=fs.begin(), e=fs.end(); i!=e; ++i)
Eat(*i);
And obviously, the problem here is that the pointer we pass to Eat() will be a Fruit*, not an Apple* or an Orange*, therefore nothing will get eaten and we will all be very hungry.
So what I really want to be able to do instead of this:
Eat(*i);
is this:
Eat(MAGIC_CAST_TO_MOST_DERIVED_CLASS(*i));
But to my limited knowledge, such magic does not exist, except possibly in the form of a big nasty if-statement full of calls to dynamic_cast.
So is there some run-time magic of which I am not aware? Or should I implement and maintain a big nasty if-statement full of dynamic_casts? Or should I suck it up, quit thinking about how I would implement this in Ruby, and allow a little Pesticide to make its way into my fruit header?
Update: Instead of the contrived bit with the bare Eat functions and Pesticide, suppose instead that I just don't want to put Eat in the fruit because it makes no sense. A fruit that knows how to eat itself? Pshaw. Instead I need an Eater class with an Eat function, with different code for eating each kind of fruit, and some default code in case it's a fruit that the eater doesn't recognize:
class Eater
{
public:
void Eat(Apple* f) { wash(); nom(); }
void Eat(Orange* f) { peel(); nom(); }
void Eat(Fruit* f) { nibble(); }
};
...
Eater me;
for(Fruits::iterator i=fs.begin(), e=fs.end(); i!=e; ++i)
me.Eat(*i); //me tarzan! me eat!
But again, this doesn't work, and the straightforward solution in C++ seems to be a bunch of calls to dynamic_cast.
However, as one of the answers suggests, there may be another clever solution. What if Fruits exposed the qualities that mattered to eaters, with functions like MustPeel() and MustWash()? Then you could get by with a single Eat() function ...
Update: Daniel Newby points out that using Visitor also solves the problem as presented ... but this requires a bit of a semantic headstand (Fruit::use or Fruit::beEaten?).
While I'd like to accept several answers, I think psmears's answer is actually the best one for future readers. Thanks, everyone.
You need to redesign. Namely, do everything you seem to be avoiding (for what reason, who knows.)
Polymorphic behavior requires polymorphic functions. This means a virtual function. (Or your ladder of dynamic_cast's, which completely defeats the purpose...)
// fruit.h
class Pesticide; // you don't need a complete type
struct Fruit
{
virtual void Eat(Pesticide*) = 0;
};
// apple.h
class Apple : public Fruit
{
void Eat(Pesticide* p) { ... }
};
// orange.h
class Orange : public Fruit
{
void Eat(Pesticide* p) { ... }
};
If you still want a free function*:
void Eat(Fruit* f, Pesticide* p) { f->Eat(p); }
*Note that your post is already indicative of bad design; namely the first Eat function:
void Eat(Fruit* f, Pesticide* p) { }
When does doing nothing to a fruit equate to eating the fruit? A pure virtual function is a much better interface choice.
When a question like this comes up, it's good to look at exactly why you want to make particular decisions - for instance, why do you not want the Fruit classes to know about Pesticide?
I'm sure there is a good reason for this - but expressing that reason will help clarify in your mind exactly what your aims are - and this often sheds a new light on a possible angle for structuring the program.
For instance, you might end up adding new virtual methods "IsEdible" and "PrepareForEating". Then you can implement these for each fruit, and implement one generic Eat method that works for all fruits - and ingests the pesky pesticide too - all without the Fruit classes knowing anything about it.
Of course, depending on your precise aims, that may be totally inappropriate - which is why you'll have to clarify the example in your own head :-)
Just use the I Am Standing Right Here! Pattern. It's like the Visitor Pattern but without a container.
// fruit.h
class Fruit;
class Apple;
class Orange;
class Fruit_user {
public:
Fruit_user();
virtual ~Fruit_user();
virtual use(Apple *f) = 0;
virtual use(Orange *f) = 0;
};
class Fruit {
public:
// Somebody with strong template fu could probably do
// it all here.
virtual void use(Fruit_user *fu) = 0;
};
class Apple : public Fruit {
public:
virtual void use(Fruit_user *fu) {
fu->use(this);
}
};
class Orange: public Fruit {
public:
virtual void use(Fruit_user *fu) {
fu->use(this);
}
};
// dow-chemical.h
class Pesticide_fruit_user : public Fruit_user {
public:
Pesticide_fruit_user(Pesticide *p) {
p_ = p;
}
virtual void use(Apple *f) { ingest(f, p_); }
virtual void use(Orange *f) { peel(f, p_); ingest(f, p_); }
private:
Pesticide *p_;
};
There's nothing wrong with having arbitrary class pointers in headers. They form the basis of many idioms, like PIMPL and opaque pointers. Also, if you aren't a sane person, how are you supposed to understand my answer?
Seriously, derived functions and polymorphism exist to solve this problem. If you refuse to use the language provided tools, why bother using it at all? Any solution you can come up with can be translated into a virtual function call in any case, just you would have coded it manually instead of having the compiler do it.
What you're asking for isn't possible. The function overloading resolution needs to know at compile time which class the parameter is so it can call the correct Eat function. The only exception is for virtual member functions, which you've already ruled out.
Related
I have a problem with typename SnakeGame. I would like to know how to make SnakeGame to global type in class KeyboardEvents. Now a nested class like DirectionKeyboard don't know what the type SnakeGame is, since it only sees see KeyboardEvents<SnakeGame> type. I don't know how to change it :P
Here's the error:
no know conversion for argument 1 from 'KeyboardEvents SnakeGame>&' to 'SnakeGame&'
I would really appreciate help .
keyboardEvents.hpp
#include<SFML/Graphics.hpp>
template <typename SnakeGame>
class KeyboardEvents {
public:
virtual ~KeyboardEvents() = default;
protected:
class DirectionKeyboardEvent{
public:
virtual ~DirectionKeyboardEvent() = default;
virtual void direction(SnakeGame&) = 0; // error no know conversion
};
class GoRight : public DirectionKeyboardEvent {
public:
void direction(SnakeGame& snakeObj) {
snakeObj.snake[0].xCoor+=1;
}
};
class GoRight : public DirectionKeyboardEvent {
public:
void direction(SnakeGame& snakeObj){
snakeObj.snake[0].xCoor += 1;
}
};
class GoLeft : public DirectionKeyboardEvent{
public:
void direction(SnakeGame& snakeObj){
snakeObj.snake[0].xCoor-=1;
}
};
class GoUp:public DirectionKeyboardEvent{
public:
void direction(SnakeGame& snakeObj){
snakeObj.snake[0].yCoor-=1;
}
};
class GoDown : public DirectionKeyboardEvent{
public:
void direction(SnakeGame& snakeObj){
snakeObj.snake[0].yCoor+=1;
}
};
std::map<sf::Keyboard::Key, std::shared_ptr<DirectionKeyboardEvent>> mapOfDirects;
void initializeDirectionMap() {
mapOfDirects[sf::Keyboard::Right] = std::shared_ptr< DirectionKeyboardEvent >(new GoRight);
mapOfDirects[sf::Keyboard::Left] = std::shared_ptr<DirectionKeyboardEvent>(new GoLeft);
mapOfDirects[sf::Keyboard::Up] = std::shared_ptr<DirectionKeyboardEvent>(new GoUp);
mapOfDirects[sf::Keyboard::Down] = std::shared_ptr<DirectionKeyboardEvent>(new GoDown);
}
void chooseMethodFromKeyboardArrows(sf::Keyboard::Key codeFromKeyboard) {
auto iterator = mapOfDirects.find(codeFromKeyboard);
if(iterator!=mapOfDirects.end()){
iterator->second->direction(*this);//left , right,up , down, pause
mainDirection=codeFromKeyboard;
} else {
mapOfDirects[mainDirection]->direction(*this);
}
}
};
Here's the class where I use KeyboardEvents ~ snakeGame.hpp
#include"keyboardEvents.hpp"
class SnakeGame:public Screen, public KeyboardEvents<SnakeGame> {
public:
SnakeGame(int size=16, int width=15, int height=15, int timeDelay=60000)
: Screen(size, width, height), KeyboardEvents<SnakeGame>(), timeDelay(timeDelay) {}
};
In your try to call the DirectionKeyboardEvent::direction inside the KeyboardEvents class.
Even if you put a template parameter that happens to be the child class, there is no means to compiler can know in advance that KeyboardEvents<SnakeGame> will absolutely be extended by the class SnakeGame.
I mean, one could write this code:
KeyboardEvents<SnakeGame> keyboardEvents;
keyboardEvents.chooseMethodFromKeyboardArrows(/* some key */);
In that case, keyboardEvents is not related that much to SnakeGame. In fact there is no SnakeGame instance created at all! The compiler is right, the function chooseMethodFromKeyboardArrows that call direction is wrong to assume that a KeyboardEvents<SnakeGame> is a SnakeGame.
Inheritance work the other way around: a SnakeGame is indeed a KeyboardEvents<SnakeGame>. The other way is false.
I could show you how "to make it work", but a warning is needed here: you are overusing inheritance, and you used it the wrong way in the case of KeyboardEvent. You really should try to rearrange things around, or you'll end up in a real mess.
The solution "make it work"
Since you are using CRTP, you can tell the compiler that KeyboardEvents<SnakeGame> is indeed, in absolutely ALL cases, being extended by SnakeGame. If that's really the case, you can just static_cast your base class to the child class:
if(iterator!=mapOfDirects.end()){
// Notice the presence of the cast here
iterator->second->direction(static_cast<SnakeGame&>(*this));
mainDirection=codeFromKeyboard;
}
The slightly better solution
You can as well using an existing instance of your snake class as parameter.
void chooseMethodFromKeyboardArrows(sf::Keyboard::Key codeFromKeyboard, SakeGame& game){
auto iterator = mapOfDirects.find(codeFromKeyboard);
if(iterator!=mapOfDirects.end()){
iterator->second->direction(game);
mainDirection=codeFromKeyboard;
} else {
mapOfDirects[mainDirection]->direction(game);
}
}
However, the best idea is to not make SnakeGame extending KeyboardEvent, but to contain it in the class instead:
struct SnakeGame : Screen {
KeyboardEvent<SnakeGame> event;
void callEvents() {
event.chooseMethodFromKeyboardArrows(/* some key */, *this);
}
};
Here's an homework for you:
Try to make the class KeyboardEvent not a template. I'm sure you can find a way to pass around your class without the use of themplates, while still accessing directly to your class SnakeGame, without casts or interfaces.
Your design seems a bit overcomplicated. I think the reason this is so is perhaps you were designing it as you went along. Sometimes it helps to sit down and think about these things first, draw boxes and lines on a whiteboard if you have to.
In any case, this isn't a direct answer to your question, it's a suggestion for an alternative based on what I'm guessing you are trying to do.
It seems to me that you're trying to implement some generic keyboard input handler and tie it in to your game. It's possible that I'm entirely wrong about this, but if not, consider something like this instead. First, a generic interface for things that receive keyboard events. It need not be a template, this isn't really a good use-case for templates:
class KeyboardEventHandler {
public:
enum Direction { Left, Right, Up, Down };
virtual ~KeyboardEventHandler () { }
virtual void onDirectionKey (Direction d) = 0;
};
Now your SnakeGame, which handles keyboard events, can inherit that and implement its own SnakeGame-specific logic:
class SnakeGame : public KeyboardEventHandler {
public:
void onDirectionKey (Direction d) {
switch (d) {
case Up: ...
case Down: ...
case Left: ...
case Right: ...
}
}
};
And then whatever bit of code you have that is actually processing keyboard events and driving all of this can just work with a KeyboardEventHandler *, which could be a SnakeGame, or could be anything else you decide to use it for in the future.
That's just one possibility for organization. For example, you could structure it like this instead, breaking out the KeyboardEvent, which could simplify future additions:
class KeyboardEvent {
public:
enum Direction { Left, Right, Up, Down };
Direction getDirection () { ... } // or whatever
};
class KeyboardEventHandler {
public:
virtual ~KeyboardEventHandler () { }
virtual void onEvent (KeyboardEvent &event) = 0;
};
With SnakeGame as:
class SnakeGame : public KeyboardEventHandler {
public:
void onEvent (KeyboardEvent &event) {
...
}
};
You could name that stuff something else besides Direction / onDirectionKey if you want, I picked that from your example but just make it something semantically appropriate that is also convenient (e.g. if you plan on expanding it to include more than just the arrows). But whatever, that's beside the point.
There are also 10 zillion other ways to skin this cat but the important take-home point is: If you're trying to make some generic interface for something, you really can't make it rely on the specific details of what inherits it, otherwise you're defeating the purpose of making it general to begin with. In that case, either it's not a good case for generic bases / inheritance, or you've just botched the design and need to sit back and rethink.
Remember: Your goal isn't to add as many classes and stuff as possible to your code; you're not going for like, an inheritance high score. Your goal is to keep your code clean, readable, maintainable, correct, possibly reusable, and to make your work easier on yourself. These are tools, don't just use them because you have them, instead use them when you need them to make your life easier.
However, all that said, this is still overkill for your specific application, although it is an interesting exercise. To be honest, in your specific case, I'd just chuck all the inheritance and such altogether and do something like:
class SnakeGame {
public:
void handleKeyPress (char c) {
// ... do the right thing here
}
}
And be done with it.
Say I'm coding a robot that processes a basket of fruit. Oranges need to be juiced, apples need to be sliced, and bananas need to be peeled. Fortunately, our robot has the exact tools needed for juicing, slicing, and peeling.
Robot::processFruit(List<Fruit*> basket)
{
foreach(Fruit *fruit, basket)
{
if( ? ) { juiceIt(fruit); }
else if( ? ) { sliceIt(fruit); }
else if( ? ) { peelIt(fruit); }
}
}
This is a generic example of a problem that I am occasionally confronted with. I have a gut feeling that there is something wrong in my design such that I am even led to a processFruit() function, as I'm using an object oriented language, but it doesn't appear to have a clean solution to this problem.
I could create an enum FruitType { Orange, Apple, Banana} then require each fruit to implement virtual FruitType fruitType(), but then it seems I'm just re-implementing a type system.
Or I could have functions virtual bool isOrange(); virtual bool isApple(); ... but as we can see that would get out of hand very quickly.
I could also use C++'s typeid, but this wikibook says
RTTI should only be used sparingly in C++ programs.
So I am reluctant to take that approach.
It seems that I must be missing something fundamental and crucial in the design of an object oriented program. C++ is all about inheritance and polymorphism, so is there a better way to approach this problem?
Update: I like the idea of having a generic process() function that all Fruit are required to implement. But what if I now want to add a Lemon and want to juice that? I don't want to duplicate the juicing code, so should I create a class Juicable : public Fruit and have Oranges and Lemons both be Juicable?
See Tell, don't ask:
Procedural code gets information then makes decisions. Object-oriented code tells objects to do things.
— Alec Sharp
You want to define a base Fruit class, which has a virtual process method. Apples, oranges and bananas would each implement their own version of process which does the correct thing for that type of fruit. All your robot needs to do is pull the next Fruit* out of the basket, and call process on it:
Robot::processFruit(List<Fruit*> basket)
{
foreach(Fruit *fruit, basket)
fruit->process();
}
The kind of if/else/else handling you're doing in your code example is exactly the kind of thing that polymorphism is meant to avoid, and it's definitely not doing this the "OOP" way.
The way I would handle this situation is to create a superclass called Fruit with a pure virtual method called process(). Orange, Apple and Banana will all superclass fruit, and each of them will provide an implementation of process() which takes the appropriate action for that particular type (i.e., subclass) of fruit.
So your loop would look more like:
Robot::processFruit(List<Fruit *> basket)
{
foreach(Fruit *fruit : basket)
{
fruit->process();
}
}
Otherwise, Robot's function would basically need a way to determine the type of fruit it's dealing with. Typically when I need to do this, I simply try to dynamic_cast<>() the Fruit pointer to whatever other type it might be. For instance, suppose I have a Fruit * to an object that is a Banana. I would take advantage of the following:
Fruit *f = new Banana();
Orange *o = dynamic_cast<Orange *>(f); // o is NULL, since f is NOT an Orange.
Banana *b = dynamic_cast<Banana *>(f); // b points to the same object as f now.
However, the first solution is, in my opinion, far cleaner and more respectful of object oriented programming. The second solution is sometimes useful, but should be used sparingly.
Update: If you really want the Robot to do the processing code, then I would suggest, instead of having the Robot call process(), have your robot class implement the processing methods, and then have the fruit itself take advantage of the robot - e.g.:
Robot::juiceIt(Orange *o)
{
// ...
}
Robot::sliceIt(Apple *a)
{
// ...
}
Robot::peelIt(Banana *b)
{
// ...
}
Orange::process(Robot *r)
{
r->juiceIt(this);
}
Apple::process(Robot *r)
{
r->sliceIt(this);
}
Banana::process(Robot *r)
{
r->peelIt(this);
}
I think #meagar has the better solution but I want to put this out there.
Robot::processFruit(List<Fruit*> basket)
{
foreach(Fruit *fruit, basket)
fruit->process(*this);
}
Orange::process(Robot & robot) {
robot.JuiceIt(*this);
}
This solution say a fruit needs a robot to process it.
If I really, really needed to solve this problem and I couldn't engineer my way around it... I'd write a type-aware double dispatch processor, and use it as a single-dispatch on the argument type only.
First, write a functions class that is a type erased function overload set. (This isn't trivial!)
typedef functions< void(Apple*), void(Orange*), void(Banana*) > processors;
Second, maintain a set of FruitTypes in a compile time list:
type_list< Apple, Orange, Banana > CanonincalFruitTypes;
typedef functions< void(Apple*), void(Orange*), void(Banana*) > FruitProcessor;
this has to be maintained somewhere. The relationship between these two lists can be automatic with a bit of work (so FruitProcessors is produced from CanonicalFruitTypes)
Next, write a reflection style dispatch:
class Fruit {
public:
virtual void typed_dispatch( FruitProcessor ) = 0;
virtual void typed_dispatch( FruitProcessor ) const = 0;
};
template<typename Derived>
class FruitImpl: public Fruit {
static_assert( std::is_base< Derived, FruitImpl<Derived> >::value, "bad CRTP" );
static_assert( /* Derived is in the Fruit type list */, "add fruit type to fruit list" );
Derived* self() { return static_cast<Derived*>(this); }
Derived const* self() const { return static_cast<Derived*>(this); }
virtual void typed_dispatch( FruitProcessor f ) final overrode {
f(self());
}
virtual void typed_dispatch( FruitProcessor f ) const final overrode {
f(self());
}
};
Use tricks to make deriving from Fruit not through a FruitImpl illegal (friend and private based stuff).
then, the Robot can go to town:
void Robot::process( Fruit* fruit ) {
fruit->typed_dispatch( MyHelperFunctor(this) );
}
where MyHelperFunctor returns a functor with overrides for the various types of Fruit the Robot can handle, and functions<...> has to be smart enough to test that each signature it supports can be handled by the passed in functor (this is the non-trivial part) and do proper dispatch to them.
If someone derived from Fruit, they do it via FruitImpl, which enforces it being in the fruit list. When the fruit list changes, the typed_dispatch signature changes, which requires that all users of it implement an override that can accept every fruit type in the list.
This allows you to decouple the virtual behavior of Fruit when processed by a Robot from the Fruit implementation itself, while enforcing compile-time checks that all types are handled. If their is a hierarchy of Fruit, the Robot's helper functor can make compile-time decisions to dispatch the call based on that heirarchy (which is translated into a run-time decision in functions). The overhead is an extra virtual function call (for the type-erased functions), and the construction of the type-erased functions object.
This is almost a text book case for the Visitor pattern. In the sample below I'm not using the standard visitor pattern class or function names, rather I'm using names that are relevant to the domain in this case - i.e. FruitProcessor and Process, rather than Visitor and Apply. I'm not going to comment much further as I think the code is pretty self explanatory other than to mention that this design requires the FruitProcessor to be manually updated when adding more types of fruit. There are various ways to handle that including registering fruit processing handlers or even using an abstract fruit processing factory (see abstract factory for more details). I would like to mention that there is another way that definitely requires a look and that was presented at boostcon by Sean Parent: see it on Youtube: Value Semantics and concept based polymorphism
class Apple;
class Orange;
class FruitProcessor
{
public:
virtual void Process(Apple& apple) = 0;
virtual void Process(Orange& orange) = 0;
};
class Fruit
{
public:
virtual void Process(FruitProcessor& proc) = 0;
};
class Apple : public Fruit
{
public:
virtual void Process(FruitProcessor& proc) override
{
proc.Process(*this);
}
};
class Orange : public Fruit
{
public:
virtual void Process(FruitProcessor& proc) override
{
proc.Process(*this);
}
};
class RobotFruitProcessor : public FruitProcessor
{
public:
virtual void Process(Apple& apple) override
{
std::cout << "Peel Apple\n";
}
virtual void Process(Orange& orange) override
{
std::cout << "Juice Orange\n";
}
};
int main()
{
std::vector<Fruit*> fruit_basket;
fruit_basket.push_back(new Apple());
fruit_basket.push_back(new Orange());
RobotFruitProcessor rfp;
for(auto f : fruit_basket)
{
f->Process(rfp);
}
return 0;
}
I'm lost and in need of some divine guidance.
First things first: assume you have some nicely-neat interfaces:
class IProduct
{
public:
virtual void DoThings();
}
enum ProductType
{
...
}
class IProducer
{
public:
virtual IProduct* Produce( ProductType type );
}
class IConsumer
{
public:
virtual void Consume( IProduct* product );
}
Its plain simple yet: abstract factory, abstract consumer who will invoke interface, gladly provided by those freshly-spawned IProducts.
But here comes the tricky part.
Assume that there are two ( or more ) parallel concrete groups:
class ConcreteProducerA : public IProducer { ... }
class ConcreteConsumerA : public IConsumer { ... }
class ConcreteProductA : public IProduct { ... }
class ConcreteProducerB : public IProducer { ... }
class ConcreteConsumerB : public IConsumer { ... }
class ConcreteProductB : public IProduct { ... }
And those concretes are reeealy different things. Like a space-shuttle parts ( with a parts factory and a shuttle assembly line ) and bags of vegetables ( with a farm and .. idk, who whould consume those vegetables? ). Yet they have that thing in general: DoThings(). Pretend that it is, like, PackAndSend(), or Serialize(), or Dispose(), whatever you like. Nothing concrete, yet legit to base a hierarchy on.
But those still have more differences, than generalities. So those ConcreteConsumers tend to use them differently. So differently, that, in fact, they absolutely MUST be sure, that it is supposed concrete type.
So here is the problem: I'm forcing the users of that hierarchy to downcast IPoduct to ConcreteProduct in their virtual overrides right now. And thats bugging me hard. I feel I'm missing something: a big flaw in hierarchy, some lack of pattern knowledge, something.
I mean, I can make sure, that ConcreteConsumerB always recieves ConcreteProductB, but it's still a downcast. And would you ever use a framework, that always passes around (void*)'s and forces you to cast it to whenewer you think is gonna come at ya?
Solutions I've already considered:
Tunnel all conctrete interfeces into IProduct. But that product gona turn into uncontrollable blob, who can Eat(), BeEaten(), Launch(), Destroy() and whoever knows what else. So this solution seems nothing better than downcasting to me.
That DoThings() can probably be decoupled from IProduct into another handler, which will be able to accept all of the concretes (Visitor-like). That way IProduct can be removed and there will be separate concrete groups. But what if there is a SemiConcrete layer, which imlements some common functionality for those concrete groups? Like labeling, morphing, massaging, whatever. Plus when there will be need to add another concrete group I'll be forced to change that visitor(s), which kinda increases coupling.
(ab)Use templates. That seems wise at the moment. Something along the lines of
template < typename _IProduct >
class IConcreteProducer : public IProducer
{
public:
virtual _IProduct* Produce( _IProduct::Type type ) = 0;
virtual _IProduct::Type DeduceType( ProductType type ) = 0;
virtual IProduct* Produce( ProductType type )
{
return IConcreteProducer<typename _IProduct>::Produce( DeduceType( type ) );
}
}
template < typename _IProduct >
class IConcreteConsumer : public IConsumer
{
public:
virtual void Consume( _IProduct* product ) = 0;
virtual void Consume( IProduct* product )
{
IConcreteConsumer<typename _IProduct>::Consume( (_IProduct*)product );
}
}
This way I'm in control of that downcast, but it is stil present.
Anyways, does this problem sound familiar to someone? Somebody seen it solved, or maybe heroicaly solved it himself? C++ solution would be awesome, but I think any staticaly-typed language will suffice.
Yet they have that thing in general: DoThings(). Pretend that it is,
like, PackAndSend(), or Serialize(), or Dispose(), whatever you like.
Nothing concrete, yet legit to base a hierarchy on.
Just because they can be in some hierarchy, doesn't mean they should. They are unrelated. I can't even fathom what value you are adding to whatever code base by generalizing shuttles and vegetables. If it doesn't add benefit to the users, then you are likely just making things more convoluted on yourself.
I would expect to see interfaces like the below. Notice they don't inherit from anything. If you have shared code, write simpler dumb concrete classes that people can reuse by composition.
template<typename T>
class Producer {
public:
virtual ~Producer() {}
virtual std::auto_ptr<T> produce() = 0;
};
template<typename T>
class Consumer {
public:
virtual ~Consumer() {}
virtual void consume(std::auto_ptr<T> val) = 0;
};
Then I'd expect to see concrete functions to create these from various sources.
typedef Producer<Shuttle> ShuttleProducer;
typedef Consumer<Shuttle> ShuttleConsumer;
std::auto_ptr<ShuttleProducer> GetShuttleProducerFromFile(...);
std::auto_ptr<ShuttleProducer> GetShuttleProducerFromTheWeb(...);
std::auto_ptr<ShuttleProducer> GetDefaultShuttleProducer();
There probably isn't a pattern for what you want to do, it is likely two patterns that you are smooshing (technical term) together. You didn't betray why these things should be sharing a code base, so we can only guess.
In the more complicated scenarios, you'll want to strictly separate use from creation though. It is perfectly valid to have different interfaces that look sort of similar, but are used differently.
class Foo {
public:
virtual ~Foo() {}
virtual void doStuff() = 0;
virtual void metamorphose() = 0;
};
class Fu {
public:
virtual ~Fu() {}
virtual void doStuff() = 0;
virtual void transmorgrify() = 0;
};
One possibility is to introduce a second layer to hot hierarchy. Derive IShuttle from IProduct, and derive that group from it. Then add an IShuttleProducer that yields an IShuttle* instead of IProduct*. This is okay, because C++ allows covariant return types for virtual functions... so long as the the new return type derives from the original, it is still considered an override.
But your design probably needs some rethinking either way.
How is this situation usually dealt with. For example, an object may need to do very specific things:
class Human
{
public:
void eat(Food food);
void drink(Liquid liquid);
String talkTo(Human human);
}
Say that this is what this class is supposed to do, but to actually do these might result in functions that are well over 10,000 lines. So you would break them down. The problem is, many of those helper functions should not be called by anything other than the function they are serving. This makes the code confusing in a way. For example, chew(Food food); would be called by eat() but should not be called by a user of the class and probably should not be called anywhere else.
How are these cases dealt with generally. I was looking at some classes from a real video game that looked like this:
class CHeli (7 variables, 19 functions)
Variables list
CatalinaHasBeenShotDown
CatalinaHeliOn
NumScriptHelis
NumRandomHelis
TestForNewRandomHelisTimer
ScriptHeliOn
pHelis
Functions list
FindPointerToCatalinasHeli (void)
GenerateHeli (b)
CatalinaTakeOff (void)
ActivateHeli (b)
MakeCatalinaHeliFlyAway (void)
HasCatalinaBeenShotDown (void)
InitHelis (void)
UpdateHelis (void)
TestRocketCollision (P7CVector)
TestBulletCollision (P7CVectorP7CVectorP7CVector)
SpecialHeliPreRender (void)
SpawnFlyingComponent (i)
StartCatalinaFlyBy (void)
RemoveCatalinaHeli (void)
Render (void)
SetModelIndex (Ui)
PreRenderAlways (void)
ProcessControl (void)
PreRender (void)
All of these look like fairly high level functions, which mean their source code must be pretty lengthy. What is good about this is that at a glance it is very clear what this class can do and the class looks easy to use. However, the code for these functions might be quite large.
What should a programmer do in these cases; what is proper practice for these types of situations.
For example, chew(Food food); would be called by eat() but should not be called by a user of the class and probably should not be called anywhere else.
Then either make chew a private or protected member function, or a freestanding function in an anonymous namespace inside the eat implementation module:
// eat.cc
// details of digestion
namespace {
void chew(Human &subject, Food &food)
{
while (!food.mushy())
subject.move_jaws();
}
}
void Human::eat(Food &food)
{
chew(*this, food);
swallow(*this, food);
}
The benefits of this approach compared to private member functions is that the implementation of eat can be changed without the header changing (requiring recompilation of client code). The drawback is that the function cannot be called by any function outside of its module, so it can't be shared by multiple member functions unless they share an implementation file, and that it can't access private parts of the class directly.
The drawback compared to protected member functions is that derived classes can't call chew directly.
The implementation of one member function is allowed to be split in whatever way you want.
A popular option is to use private member functions:
struct Human
{
void eat();
private:
void chew(...);
void eat_spinach();
...
};
or to use the Pimpl idiom:
struct Human
{
void eat();
private:
struct impl;
std::unique_ptr<impl> p_impl;
};
struct Human::impl { ... };
However, as soon as the complexity of eat goes up, you surely don't want a collection of private methods accumulating (be it inside a Pimpl class or inside a private section).
So you want to break down the behavior. You can use classes:
struct SpinachEater
{
void eat_spinach();
private:
// Helpers for eating spinach
};
...
void Human::eat(Aliment* e)
{
if (e->isSpinach()) // Use your favorite dispatch method here
// Factories, or some sort of polymorphism
// are possible ideas.
{
SpinachEater eater;
eater.eat_spinach();
}
...
}
with the basic principles:
Keep it simple
One class one responsibility
Never duplicate code
Edit: A slightly better illustration, showing a possible split into classes:
struct Aliment;
struct Human
{
void eat(Aliment* e);
private:
void process(Aliment* e);
void chew();
void swallow();
void throw_up();
};
// Everything below is in an implementation file
// As the code grows, it can of course be split into several
// implementation files.
struct AlimentProcessor
{
virtual ~AlimentProcessor() {}
virtual process() {}
};
struct VegetableProcessor : AlimentProcessor
{
private:
virtual process() { std::cout << "Eeek\n"; }
};
struct MeatProcessor
{
private:
virtual process() { std::cout << "Hmmm\n"; }
};
// Use your favorite dispatch method here.
// There are many ways to escape the use of dynamic_cast,
// especially if the number of aliments is expected to grow.
std::unique_ptr<AlimentProcessor> Factory(Aliment* e)
{
typedef std::unique_ptr<AlimentProcessor> Handle;
if (dynamic_cast<Vegetable*>(e))
return Handle(new VegetableProcessor);
else if (dynamic_cast<Meat*>(e))
return Handle(new MeatProcessor);
else
return Handle(new AlimentProcessor);
};
void Human::eat(Aliment* e)
{
this->process(e);
this->chew();
if (e->isGood()) this->swallow();
else this->throw_up();
}
void Human::process(Aliment* e)
{
Factory(e)->process();
}
One possibility is to (perhaps privately) compose the Human of smaller objects that each do a smaller part of the work. So, you might have a Stomach object. Human::eat(Food food) would delegate to this->stomach.digest(food), returning a DigestedFood object, which the Human::eat(Food food) function processed further.
Function decomposition is something that is learnt from experience, and it usually implies type decomposition at the same time. If your functions become too large there are different things that can be done, which is best for a particular case depends on the problem at hand.
separate functionality into private functions
This makes more sense when the functions have to access quite a bit of state from the object, and if they can be used as building blocks for one or more of the public functions
decompose the class into different subclasses that have different responsibilities
In some cases a part of the work falls naturally into its own little subproblem, then the higher level functions can be implemented in terms of calls to the internal subobjects (usually members of the type).
Because the domain that you are trying to model can be interpreted in quite a number of different ways I fear trying to provide a sensible breakdown, but you could imagine that you had a mouth subobject in Human that you could use to ingest food or drink. Inside the mouth subobject you could have functions open, chew, swallow...
Okay, so you have a load of methods sprinkled around your system's main class. So you do the right thing and refactor by creating a new class and perform move method(s) into a new class. The new class has a single responsibility and all is right with the world again:
class Feature
{
public:
Feature(){};
void doSomething();
void doSomething1();
void doSomething2();
};
So now your original class has a member variable of type object:
Feature _feature;
Which you will call in the main class. Now if you do this many times, you will have many member-objects in your main class.
Now these features may or not be required based on configuration so in a way it's costly having all these objects that may or not be needed.
Can anyone suggest a way of improving this?
EDIT: Based on suggestion to use The Null Object Design Pattern I've come up with this:
An Abstract Class Defining the Interface of the Feature:
class IFeature
{
public:
virtual void doSomething()=0;
virtual void doSomething1()=0;
virtual void doSomething2()=0;
virtual ~IFeature(){}
};
I then define two classes which implement the interface, one real implementation and one Null Object:
class RealFeature:public IFeature
{
public:
RealFeature(){};
void doSomething(){std::cout<<"RealFeature doSomething()"<<std::endl;}
void doSomething1(){std::cout<<"RealFeature doSomething()"<<std::endl;}
void doSomething2(){std::cout<<"RealFeature doSomething()"<<std::endl;}
};
class NullFeature:public IFeature
{
public:
NullFeature(){};
void doSomething(){std::cout<<"NULL doSomething()"<<std::endl;};
void doSomething1(){std::cout<<"NULL doSomething1()"<<std::endl;};
void doSomething2(){std::cout<<"NULL doSomething2()"<<std::endl;};
};
I then define a Proxy class which will delegate to either the real object or the null object depending on configuration:
class Feature:public IFeature
{
public:
Feature();
~Feature();
void doSomething();
void doSomething1();
void doSomething2();
private:
std::auto_ptr<IFeature> _feature;
};
Implementation:
Feature::Feature()
{
std::cout<<"Feature() CTOR"<<std::endl;
if(configuration::isEnabled() )
{
_feature = auto_ptr<IFeature>( new RealFeature() );
}
else
{
_feature = auto_ptr<IFeature>( new NullFeature() );
}
}
void Feature::doSomething()
{
_feature->doSomething();
}
//And so one for each of the implementation methods
I then use the proxy class in my main class (or wherever it's required):
Feature _feature;
_feature.doSomething();
If a feature is missing and the correct thing to do is ignore that fact and do nothing, you can get rid of your checks by using the Null Object pattern:
class MainThing {
IFeature _feature;
void DoStuff() {
_feature.Method1();
_feature.Method2();
}
interface IFeature {
void Method1();
void Method2();
}
class SomeFeature { /* ... */ }
class NullFeature {
void Method1() { /* do nothing */ }
void Method2() { /* do nothing */ }
}
Now, in MainThing, if the optional feature isn't there, you give it a reference to a NullFeature instead of an actual null reference. That way, MainThing can always safely assume that _feature isn't null.
An auto_ptr by itself won't buy you much. But having a pointer to an object that you lazily load only when and if you need it might. Something like:
class Foo {
private:
Feature* _feature;
public:
Foo() : _feature(NULL) {}
Feature* getFeature() {
if (! _feature) {
_feature = new Feature();
}
return _feature;
}
};
Now you can wrap that Feature* in a smart pointer if you want help with the memory management. But the key isn't in the memory management, it's the lazy creation. The advantage to this instead of selectively configuring what you want to go create during startup is that you don't have to configure – you simply pay as you go. Sometimes that's all you need.
Note that a downside to this particular implementation is that the creation now takes place the first time the client invokes what they think is just a getter. If creation of the object is time-consuming, this could be a bit of a shock to, or even a problem for, to your client. It also makes the getter non-const, which could also be a problem. Finally, it assumes you have everything you need to create the object on demand, which could be a problem for objects that are tricky to construct.
There is one moment in your problem description, that actually would lead to failure. You shouldn't "just return" if your feature is unavailable, you should check the availability of your feature before calling it!
Try designing that main class using different approach. Think of having some abstract descriptor of your class called FeatureMap or something like that, which actually stores available features for current class.
When you implement your FeatureMap everything goes plain and simple. Just ensure (before calling), that your class has this feature and only then call it. If you face a situation when an unsupported feature is being called, throw an exception.
Also to mention, this feature-lookup routine should be fast (I guess so) and won't impact your performance.
I'm not sure if I'm answering directly to your question (because I don't have any ideas about your problem domain and, well, better solutions are always domain-specific), but hope this will make you think in the right way.
Regarding your edit on the Null Object Pattern: If you already have a public interface / private implementation for a feature, it makes no sense to also create a null implementation, as the public interface can be your null implementation with no problems whatsoever).
Concretely, you can have:
class FeatureImpl
{
public:
void doSomething() { /*real work here*/ }
};
class Feature
{
class FeatureImpl * _impl;
public:
Feature() : _impl(0) {}
void doSomething()
{
if(_impl)
_impl->doSomething();
// else case ... here's your null object implementation :)
}
// code to (optionally) initialize the implementation left out due to laziness
};
This code only benefits from a NULL implementation if it is performance-critical (and even then, the cost of an if(_impl) is in most cases negligible).