Sometimes when fixing a defect in an existing code base I might (often out of laziness) decide to change a method from:
void
MyClass::foo(uint32_t aBar)
{
// Do something with aBar...
}
to:
void
MyClass::foo(uint32_t aBar, bool aSomeCondition)
{
if (aSomeCondition)
{
// Do something with aBar...
}
}
During a code review a colleague mentioned that a better approach would be to sub-class MyClass to provide this specialized functionality.
However, I would argue that as long as aSomeCondition doesn't violate the purpose or cohesion of MyClass it is an acceptable pattern to use. Only if the code became infiltrated with flags and if statements would inheritance be a better option, otherwise we would be potentially be entering architecture astronaut territory.
What's the tipping point here?
Note: I just saw this related answer which suggests that an enum may be a better
choice than a bool, but I think my question still applies in this case.
There is not only one solution for this kind of problem.
Boolean has a very low semantic. If you want to add in the future a new condition you will have to add a new parameter...
After four years of maintenance your method may have half a dozen of parameters, if these parameters are all boolean it is very nice trap for maintainers.
Enum is a good choice if cases are exclusive.
Enums can be easily migrated to a bit-mask or a context object.
Bit mask : C++ includes C language, you can use some plain old practices. Sometime a bit mask on an unsigned int is a good choice (but you loose type checking) and you can pass by mistake an incorrect mask. It is a convenient way to move smoothly from a boolean or an enum argument to this kind of pattern.
Bit mask can be migrated with some effort to a context-object. You may have to implement some kind of bitwise arithmetics such as operator | and operator & if you have to keep a buildtime compatibility.
Inheritence is sometime a good choice if the split of behavior is big and this behavior IS RELATED to the lifecycle of the instance. Note that you also have to use polymorphism and this is may slow down the method if this method is heavily used.
And finally inheritence induce change in all your factory code... And what will you do if you have several methods to change in an exclusive fashion ? You will clutter your code of specific classes...
In fact, I think that this generally not a very good idea.
Method split : Another solution is sometime to split the method in several private and provide two or more public methods.
Context object : C++ and C lack of named parameter can be bypassed by adding a context parameter. I use this pattern very often, especially when I have to pass many data across level of a complex framework.
class Context{
public:
// usually not a good idea to add public data member but to my opinion this is an exception
bool setup:1;
bool foo:1;
bool bar:1;
...
Context() : setup(0), foo(0), bar(0) ... {}
};
...
Context ctx;
ctx.setup = true; ...
MyObj.foo(ctx);
Note:
That this is also useful to minimize access (or use) of static data or query to singleton object, TLS ...
Context object can contain a lot more of caching data related to an algorithm.
...
I let your imagination run free...
Anti patterns
I add here several anti pattern (to prevent some change of signature):
*NEVER DO THIS *
*NEVER DO THIS * use a static int/bool for argument passing (some people that do that, and this is a nightmare to remove this kind of stuff). Break at least multithreading...
*NEVER DO THIS * add a data member to pass parameter to method.
Unfortunately, I don't think there is a clear answer to the problem (and it's one I encounter quite frequently in my own code). With the boolean:
foo( x, true );
the call is hard to understand .
With an enum:
foo( x, UseHigherAccuracy );
it is easy to understand but you tend to end up with code like this:
foo( x, something == someval ? UseHigherAccuracy : UseLowerAccuracy );
which is hardly an improvement. And with multiple functions:
if ( something == someval ) {
AccurateFoo( x );
}
else {
InaccurateFoo( x );
}
you end up with a lot more code. But I guess this is the easiest to read, and what I'd tend to use, but I still don't completely like it :-(
One thing I definitely would NOT do however, is subclass. Inheritance should be the last tool you ever reach for.
The primary question is if the flag affects the behaviour of the class, or of that one function. Function-local changes should be parameters, not subclasses. Run-time inheritance should be one of the last tools reached for.
The general guideline I use is: if aSomeCondition changes the nature of the function in a major way, then I consider subclassing.
Subclassing is a relatively large effort compared to adding a flag that has only a minor effect.
Some examples:
if it's a flag that changes the direction in which a sorted collection is returned to the caller, that's a minor change in nature (flag).
if it's a one-shot flag (something that affects the current call rather than a persistent change to the object), it should probably not be a subclass (since going down that track is likely to lead to a massive number of classes).
if it's a enumeration that changes the underlying data structure of your class from array to linked list or balanced tree, that's a complex change (subclass).
Of course, that last one may be better handled by totally hiding the underlying data structure but I'm assuming here that you want to be able to select one of many, for reasons such as performance.
IMHO, aSomeCondition flag changes or depends on the state of current instance, therefore, under certain conditions this class should change its state and handle mentioned operation differently. In this case, I can suggest the usage of State Pattern. Hope it helps.
I would just change code:
void MyClass::foo(uint32_t aBar, bool aSomeCondition)
{
if (aSomeCondition)
{
// Do something with aBar...
}
}
to:
void MyClass::foo(uint32_t aBar)
{
if (this->aSomeCondition)
{
// Do something with aBar...
}
}
I always omit bool as function parameter and prefer to put into struct, even if I would have to call
myClass->enableCondition();
Related
Okay, just about everywhere I read, I read that getters/setters are "evil".
Now, as a programmer who uses getters/setters often in PHP / C#, I do not see how they are alive. I have read that they break encapsulation, etc etc, however, here is a simple example.
class Armor{
int armorValue;
public:
Armor();
Armor(int); //int here represents armor value
int GetArmorValue();
void SetArmorValue(int);
};
Now, lets say getters and setters are "evil".
How are you supposed to change a member variable after initialization.
Example:
Armor arm=Armor(128); //armor with 128 armor value
//for some reason I would like to change this armor value
arm.SetArmorValue(55); //if i do not use getters / setters how is this possible?
Lets say the above is not okay, for whatever reason.
What if my game restricts armor values from 1 to 500. (No armor can have a piece that has more than 500 armor or less than 1 armor).
Now my implementation becomes
void Armor::SetArmor(int tArmValue){
if (tArmValue>=1 && tArmValue<=500)
armorValue=tArmValue;
else
armorValue=1;
}
So, how else would I impose this restriction without using getters/setters?
How else would I modify a property without using getters/setters?
Should armorValue just be a public member variable in case 1, and the getters/setters used in case 2?
Curious. THanks guys
You have misunderstood something. Not using getters/setters breaks encapsulation and exposes implementation details, and can be considered "evil" for some definition of evil.
I guess they can be considered evil in the sense, that without proper IDE/editor support, they are somewhat tediois to write in C++...
One pitfall of C++ is to create non-const reference getter, which allows also modification. That's same as returning a pointer to internal data, and will lock that part of internal implementation, and is really no better than making field public.
Edit: based on comments and other answers, what you heard probably refers to always creating non-private getter and setter for every field. But I would not call that evil either, just stupid ;-)
Being slightly contrarian: yes, getters and setters (aka accessors and mutators) are mostly evil.
The evil here is not, IMO, so much from "breaking encapsulation", as from simply defining a variable to be of one type (e.g., int) when it's really not that type at all. Looking at your example, you're calling Armor an int, but it's really not. While it's undoubtedly an integer, it's certainly not an int, which (among other things) defines a range. While your type is an integer, it's never intended to support the same range as an int at all. If you want Armor to be of a type integer from 1 to 500, define a type to represent that directly, and define Armor as an instance of that type. In this case, since the invariant you want to enforce is defined as part of the type itself, you don't need to tack a setter onto it to try to enforce it.
template <class T, class less=std::less<T> >
class bounded {
const T lower_, upper_;
T val_;
bool check(T const &value) {
return less()(value, lower_) || less()(upper_, value);
}
void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}
public:
bounded(T const &lower, T const &upper)
: lower_(lower), upper_(upper) {}
bounded(bounded const &init)
: lower_(init.lower), upper_(init.upper), val_(init.val_)
{ }
bounded &operator=(T const &v) { assign(v); return *this; }
operator T() const { return val_; }
friend std::istream &operator>>(std::istream &is, bounded &b) {
T temp;
is >> temp;
if (b.check(temp))
is.setstate(std::ios::failbit);
else
b.val_ = temp;
return is;
}
};
With this in place, defining some armor with a range of 1..500 becomes utterly trivial:
bounded<int> armor(1, 500);
Depending on the situation, you might prefer to define (for example) a saturating type where attempting to assign an out of range value is fine, but the value that actually is assigned will simply be the nearest value that is within range.
saturating<int> armor(1, 500);
armor = 1000;
std::cout << armor; // prints "500"
Of course, what I've given above is also a bit bare-bones. For your armor type, it would probably be convenient to support -= (and possibly +=) so an attack would end up something like x.armor -= 10;.
Bottom line: the (or at least "one") major problem with getters and setters is that they usually point to your having defined a variable as being of one type when you really want some other type that happened to be sort of similar in a few ways.
Now, it's true that some languages (e.g., Java) fail to provide the programmer with the tools necessary to write code like that. Here I'm trusting your use of the C++ tag to indicate that you really do want to write C++ though. C++ does provide you with the necessary tools, and (at least IMO) your code will be better off for your making good use of the tools it provides so your type enforces the required semantic constraints while still using clean, natural, readable syntax.
In short: they aren't evil.
It's nothing wrong with them as long as they don't leak out the internal representation. I see no problems here.
A common criticism of get/set functions is that they can be abused by client code to perform operations that logically should be encapsulated in the class. For example, say a client wants to "polish" their armour, and decides the effect is to increase "value" by 20, so they do their little get and set thing and are happy. Then someone other client code elsewhere decides rusty armour should drop the value by 30, and they do their bit. Meanwhile, a dozen other places in client code are also allowing polishing and rusting effects on armour - as well as say "reinforcing" and "cracking", and implementing them directly. There's no central control of this... the maintainer of the armour class has no ability to do things like:
have the rust, polish, reinforce and crack effects apply at most once per piece of armour
tune the number added to or subtract from value for specific logical effects
decide that the new "leather" armour type can't rust, and ignore client attempts to make it do so
On the other hand, if the first client that wanted to make armour rusty couldn't do so through the interface, they'd go to the maintainer of the armour class and say "hey, give me a function to do this", then other people could start using the logical-level "rust" operation, and if it became useful later to do the kinds of things I describe above they could be implemented easily and centrally in the armour class (e.g. by having a separate boolean to say if the armour was rusty, or a separate variable recording the rust effect).
So, the thing with get/set functions is they frustrate the natural evolution of an API of logical functionality, instead distributing logic throughout client code, leading in extremis to an unmaintainable mess.
Your getter/setter looks ok.
The alternative to getter/setters is to make member variables public. To be more precise, group variables into structure without member functions. And operate on this structure within your class
Giving access to members reduces encapsulation, but sometimes it's necessary. And the best way to do it is by means of getters and setters. Some people implement them when no such access is necessary, just because they can and it's a habit.
Getters are evil whenever:
They access directly data members of the class
When you have to add new getter every time you add data to the class
The data behaviour is different in each getter
Good getters would thus do the following:
They forward the request to some other object or collect the data from several places
You can fetch large amounts of data using just one getter
All the data you fetch is handled the same way
Setters on the other hand are evil always.
how else would I impose this restriction without using getters/setters? How else would I modify a property without using getters/setters?
You can check what you read from the variable and if its value is out of range use a predefined value instead (if possible).
You can also resort to dirty hacks such as protecting the memory underneath the variable from writing, catching write attempts and disallowing/ignoring the ones with invalid values. This is going to be cumbersome to implement and expensive to execute. It may be useful for debugging, though.
So I have this huge tree that is basically a big switch/case with string keys and different function calls on one common object depending on the key and one piece of metadata.
Every entry basically looks like this
} else if ( strcmp(key, "key_string") == 0) {
((class_name*)object)->do_something();
} else if ( ...
where do_something can have different invocations, so I can't just use function pointers. Also, some keys require object to be cast to a subclass.
Now, if I were to code this in a higher level language, I would use a dictionary of lambdas to simplify this.
It occurred to me that I could use macros to simplify this to something like
case_call("key_string", class_name, do_something());
case_call( /* ... */ )
where case_call would be a macro that would expand this code to the first code snippet.
However, I am very much on the fence whether that would be considered good style. I mean, it would reduce typing work and improve the DRYness of the code, but then it really seems to abuse the macro system somewhat.
Would you go down that road, or rather type out the whole thing? And what would be your reasoning for doing so?
Edit
Some clarification:
This code is used as a glue layer between a simplified scripting API which accesses several different aspects of a C++ API as simple key-value properties. The properties are implemented in different ways in C++ though: Some have getter/setter methods, some are set in a special struct. Scripting actions reference C++ objects casted to a common base class. However, some actions are only available on certain subclasses and have to be cast down.
Further down the road, I may change the actual C++ API, but for the moment, it has to be regarded as unchangeable. Also, this has to work on an embedded compiler, so boost or C++11 are (sadly) not available.
I would suggest you slightly reverse the roles. You are saying that the object is already some class that knows how to handle a certain situation, so add a virtual void handle(const char * key) in your base class and let the object check in the implementation if it applies to it and do whatever is necessary.
This would not only eliminate the long if-else-if chain, but would also be more type safe and would give you more flexibility in handling those events.
That seems to me an appropriate use of macros. They are, after all, made for eliding syntactic repetition. However, when you have syntactic repetition, it’s not always the fault of the language—there are probably better design choices out there that would let you avoid this decision altogether.
The general wisdom is to use a table mapping keys to actions:
std::map<std::string, void(Class::*)()> table;
Then look up and invoke the action in one go:
object->*table[key]();
Or use find to check for failure:
const auto i = table.find(key);
if (i != table.end())
object->*(i->second)();
else
throw std::runtime_error(...);
But if as you say there is no common signature for the functions (i.e., you can’t use member function pointers) then what you actually should do depends on the particulars of your project, which I don’t know. It might be that a macro is the only way to elide the repetition you’re seeing, or it might be that there’s a better way of going about it.
Ask yourself: why do my functions take different arguments? Why am I using casts? If you’re dispatching on the type of an object, chances are you need to introduce a common interface.
In couple of recent projects that I took part in I was almost addicted to the following coding pattern: (I'm not sure if there is a proper name for this, but anyway...)
Let's say some object is in some determined state and we wan't to change this state from outside. These changes could mean any behaviour, could invoke any algorithms, but the fact is that they focus on changing the state (member state, data state, etc...) of some object.
And let's call one discrete way of changing those object a Mutator. Mutators are applied once (generally) and they have some internal method like apply(Target& target, ...), which instantly provokes changing the state of the object (in fact, they're some sort of functional objects).
They also could be easily assimilated into chains and applied one-by-one (Mutator m1, m2, ...); they also could derive from some basic BasicMutator with virtual void apply(...) method.
I have introduced classes called InnerMutator and ExplicitMutator which differ in terms of access - first of them can also change the internal state of the object and should be declared as a friend (friend InnerMutator::access;).
In those projects my logic turned to work the following way:
Prepare available mutators, choose which to apply
Create and set the object to some determined state
foreach (mutator) mutator.apply(object);
Now the question.
This scheme turnes to work well and
(to me) seems as a sample of some non-standard but useful design
pattern.
What makes me feel uncomfortable is that InnerMutator stuff. I don't
think declaring mutator a friend to
every object which state could be
changed is a good idea and I wan't to
find the appropriate alternative.
Could this situation be solved in terms of Mutators or could you
advice some alternative pattern with
the same result?
Thanks.
I hope this isn't taken offensively, but I can't help but think this design is an overly fancy solution for a rather simple problem.
Why do you need to aggregate mutators, for instance? One can merely write:
template <class T>
void mutate(T& t)
{
t.mutate1(...);
t.mutate2(...);
t.mutate3(...);
}
There's your aggregate mutator, only it's a simple function template relying on static polymorphism rather than a combined list of mutators making one super-mutator.
I once did something that might have been rather similar. I made function objects which could be combined by operator && into super function objects that applied both operands (in the order from left to right) so that one could write code like:
foreach(v.begin(), v.end(), attack && burn && drain);
It was really neat and seemed really clever to me at the time and it was pretty efficient because it generated new function objects on the fly (no runtime mechanisms involved), but when my co-workers saw it, they thought I was insane. In retrospect I was trying to cram everything into functional style programming which has its usefulness but probably shouldn't be over-relied on in C++. It would have been easy enough to write:
BOOST_FOR_EACH(Something& something, v)
{
attack(something);
burn(something);
drain(something);
}
Granted it is more lines of code but it has the benefit of being centralized and easy to debug and doesn't introduce alien concepts to other people working with my code. I've found it much more beneficial instead to focus on tight logic rather than trying to forcefully reduce lines of code.
I recommend you think deeply about this and really consider if it's worth it to continue with this mutator-based design no matter how clever and tight it is. If other people can't quickly understand it, unless you have the authority of boost authors, it's going to be hard to convince people to like it.
As for InnerMutator, I think you should avoid it like the plague. Having external mutator classes which can modify a class's internals as directly as they can here defeats a lot of the purpose of having internals at all.
Would it not be better to simply make those Mutators methods of the classes they're changing? If there's common functionality you want several classes to have then why not make them inherit from the same base class? Doing this will deal with all the inner mutator discomfort I would imagine.
If you want to queue up changes you could store them as sets of function calls to the methods within the classes.
I'm working on a small roguelike game, and for any object/"thing" that is not a part of the map is based off an XEntity class. There are several classes that depend on it, such as XPlayer, XItem, and XMonster.
My problem is, that I want to convert a pointer from XEntity to XItem when I know that an object is in item. The sample code I am using to pick up an item is this, it is when a different entity picks up an item it is standing over.
void XEntity::PickupItem()
{
XEntity *Ent = MapList; // Start of a linked list
while(true)
{
if(Ent == NULL) { break; }
if(Ent->Flags & ENT_ITEM)
{
Ent->RemoveEntity(); // Unlink from the map's linked list
XItem *Item = Ent // Problem is here, type-safety
// Code to link into inventory is here
break;
}
Ent = Ent->MapList;
}
}
My first thought was to create a method in XEntity that returns itself as an XItem pointer, but it creates circular dependencies that are unresolvable.
I'm pretty stumped about this one. Any help is greatly appreciated.
If you know that the XEntity is actuall and XItem then you can use a static cast.
XItem* Item = static_cast<XItem *>(Ent);
However, you should review you design and see if you can operate on the entity in a way that means that you don't need to know what derived type it is. If you can give the base class a sufficiently rich interface you may be able eliminate the flag check type inspection.
Casting solves the problem as others have pointed out:
// dynamic_cast validates that the cast is possible. It requires RTTI
// (runtime type identification) to work. It will return NULL if the
// cast is not possible.
XItem* Item = dynamic_cast<XItem*>(Ent);
if(Item)
{
// Do whatever you want with the Item.
}
else
{
// Possibly error handling code as Ent is not an Item.
}
However I think that you sould step back and look at the design of the program, as downcasting is something that should and can be avoided by a proper object-oriented design. One powerful, even though a bit complex, tool might be the Visitor pattern.
I used to believe that downcasting was always possible to avoid with a "proper" design. This just isn't the case though. A proper design very often needs to have sub-objects that implement new, and not just different behavior. Too often advocates of "proper" design will tell you to move the new behavior up the stack of abstraction to places where it doesn't belong. Not always, but if you keep trying to make sure all your classes can be used from the most abstract point this is very often where things end up going and it's just fugly.
One great way to deal with downcasting in a centralized manner is by using the Visitor pattern. There are several forms of visitor though, some require downcasting, some do not. The acyclic visitor, the one that does require downcasting, is easier to work with and is, in my experience, more powerful.
Another visitor that I've not attempted to work with claims to meet the same flexibility of acyclic visitor with the speed of the standard visitor; it's called "cooperative visitor". It still casts, it just does so in a quicker manner with it's own lookup table. The reason I have not tried the cooperative visitor is that I've not found a way to make it work on multiple higherarchies...but I've not spent a lot of time on it either because I've stuck myself (in my current project) with acyclic.
The real cool thing about the cooperative visitor is return types. However, I use my visitors to visit entire blocks of objects and do things with them. I have trouble envisioning how a return would work in these cases.
The standard visitor downcasts also it just does so through the virtual call mechanism, which is faster and sometimes safer than an explicit cast. The thing I don't like about this visitor is that if you need to visit WidgetX in the Widget higherarchy then you also have to implement visit() functionality for WidgetY and WidgetZ even though you don't care about them. With large and/or wide higherarchies this can be a PITA. Other options do not require this.
There is also a "higherarchal visitor". It knows when to quit.
If you're not inclined to use a visitor though and wish to just cast then you might consider using the boost::polymorphic_downcast function. It has the safety and warning mechanisms of dynamic cast with asserts in debug builds, and the speed of static cast in a release. It may not be necessary though. Sometimes you just know that you're casting right.
The important thing that you need to think about and what you want to avoid, is breaking the LSP. If you have a whole lot of code with "if (widget->type() == type1) { downcast...} else if (widget->type() == type2)..." then adding new widget types is a big issue that affects a lot of code in a bad way. Your new widget won't really be a widget because all your clients are too intimate with your higherarchy and don't know about it. The visitor pattern does not get rid of this issue but it does centralize, which is very important when you've got a bad smell, and it often makes it simpler to deal with on top of it.
Just cast it:
XItem* Item = (XItem*)Ent;
A better approach, overall, is this:
if (XItem *Item = dynamic_cast<XItem*>(Ent)) {
Ent->RemoveEntity();
// Code to link into inventory is here
break;
}
XItem * Item = dynamic_cast< XItem * >( Ent );
if ( Item )
// do something with item
In order for that to work, you need to enable RTTI. Look here for more information.
As have been answered, there are 2 operators:
XItem* Item = static_cast<XItem*>(Ent);
And:
XItem* Item = dynamic_cast<XItem*>(Ent);
the second is slower but safer (it checks if it's possible) and might return null even if Ent is not.
I tend to use both wrapped in a method:
template <class T, class U>
T* my_cast(U* item)
{
#ifdef _NDEBUG_
if (item) return &dynamic_cast<T&>(*item); // throw std::bad_cast
else return 0;
#else
return static_cast<T*>(item);
#endif
}
This way I get type checking while development (with an exception if something goes bad) and I get speed when I'm finished. You can use other strategies if you wish, but I must admit I quite like this way :)
A scene like this:
I've different of objects do the similar operation as respective func() implements.
There're 2 kinds of solution for func_manager() to call func() according to different objects
Solution 1: Use virtual function character specified in c++. func_manager works differently accroding to different object point pass in.
class Object{
virtual void func() = 0;
}
class Object_A : public Object{
void func() {};
}
class Object_B : public Object{
void func() {};
}
void func_manager(Object* a)
{
a->func();
}
Solution 2: Use plain switch/case. func_manager works differently accroding to different type pass in
typedef enum _type_t
{
TYPE_A,
TYPE_B
}type_t;
void func_by_a()
{
// do as func() in Object_A
}
void func_by_b()
{
// do as func() in Object_A
}
void func_manager(type_t type)
{
switch(type){
case TYPE_A:
func_by_a();
break;
case TYPE_B:
func_by_b();
default:
break;
}
}
My Question are 2:
1. at the view point of DESIGN PATTERN, which one is better?
2. at the view point of RUNTIME EFFCIENCE, which one is better? Especailly as the kinds of Object increases, may be up to 10-15 total, which one's overhead oversteps the other? I don't know how switch/case implements innerly, just a bunch of if/else?
Thanks very much!
from the view point of DESIGN PATTERN, which one is better?
Using polymorphism (Solution 1) is better.
Just one data point: Imagine you have a huge system built around either of the two and then suddenly comes the requirement to add another type. With solution one, you add one derived class, make sure it's instantiated where required, and you're done. With solution 2 you have thousands of switch statements smeared all over the system and it is more or less impossible to guarantee you found all the places where you have to modify them for the new type.
from the view point of RUNTIME EFFCIENCE, which one is better? Especailly as the kinds of Object
That's hard to say.
I remember a footnote in Stanley Lippmann's Inside the C++ Object Model, where he says that studies have shown that virtual functions might have a small advantage against switches over types. I would be hard-pressed, however, to cite chapter and verse, and, IIRC, the advantage didn't seem big enough to make the decision dependent on it.
The first solution is better if only because it's shorter in code. It is also easier to maintain and faster to compile: if you want to add types you need only add new types as headers and compilation units, with no need to change and recompile the code that is responsible for the type mapping. In fact, this code is generated by the compiler and is likely to be as efficient or more efficient than anything you can write on your own.
Virtual functions at the lowest level cost no more than an extra dereference in a table (array). But never mind that, this sort of performance nitpicking really doesn't matter at this microscopic numbers. Your code is simpler, and that's what matters. The runtime dispatch that C++ gives you is there for a reason. Use it.
I would say the first one is better. In solution 2 func_manager will have to know about all types and be updated everytime you add a new type. If you go with solution 1 you can later add a new type and func_manager will just work.
In this simple case I would actually guess that solution 1 will be faster since it can directly look up the function address in the vtable. If you have 15 different types the switch statement will likely not end up as a jump table but basically as you say a huge if/else statement.
From the design point of view the first one is definitely better as thats what inheritance was intended for, to make different objects behave homogeneously.
From the efficiency point of view in both alternatives you have more or less the same generated code, somewhere there must be the choice making code. Difference is that inheritance handles it for you automatically in the 1st one and you do it manually in the 2nd one.
Using "dynamic dispatch" or "virtual dispatch" (i.e. invoking a virtual function) is better both with respect to design (keeping changes in one place, extensibility) and with respect to runtime efficiency (simple dereference vs. a simple dereference where a jump table is used or an if...else ladder which is really slow). As a slight aside, "dynamic binding" doesn't mean what you think... "dynamic binding" refers to resolving a variable's value based on its most recent declaration, as opposed to "static binding" or "lexical binding", which refers to resolving a variable by the current inner-most scope in which it is declared.
Design
If another programmer comes along who doesn't have access to your source code and wants to create an implementation of Object, then that programmer is stuck... the only way to extend functionality is by adding yet another case in a very long switch statement. Whereas with virtual functions, the programmer only needs to inherit from your interface and provide definitions for the virtual methods and, walla, it works. Also, those switch statements end up all over the place, and so adding new implementations almost always requires modifying many switch statements everywhere, while inheritance keeps the changes localized to one class.
Efficiency
Dynamic dispatch simply looks up a function in the object's virtual table and then jumps to that location. It is incredibly fast. If the switch statement uses a jump table, it will be roughly the same speed; however, if there are very few implementations, some programmer is going to be tempted to use an if...else ladder instead of a switch statement, which generally is not able to take advantage of jump tables and is, therefore, slower.
Why nobody suggests function objects? I think kingkai interested in solving the problem, not only that two solutions.
I'm not experienced with them, but they do their job:
struct Helloer{
std::string operator() (void){
return std::string("Hello world!");
}
};
struct Byer{
std::string operator() (void){
return std::string("Good bye world!");
}
};
template< class T >
void say( T speaker){
std::cout << speaker() << std::endl;
}
int main()
{
say( Helloer() );
say( Byer() );
}
Edit: In my opinion this is more "right" approach, than classes with single method (which is not function call operator). Actually, I think this overloading was added to C++ to avoid such classes.
Also, function objects are more convenient to use, even if you dont want templates - just like usual functions.
In the end consider STL - it uses func objects everywhere and looks pretty natural. And I dont even mention Boost