I'm in a situation where I have a class, let's call it Generic. This class has members and attributes, and I plan to use it in a std::vector<Generic> or similar, processing several instances of this class.
Also, I want to specialize this class, the only difference between the generic and specialized objects would be a private method, which does not access any member of the class (but is called by other methods). My first idea was to simply declare it virtual and overload it in specialized classes like this:
class Generic
{
// all other members and attributes
private:
virtual float specialFunc(float x) const =0;
};
class Specialized_one : public Generic
{
private:
virtual float specialFunc(float x) const{ return x;}
};
class Specialized_two : public Generic
{
private:
virtual float specialFunc(float x) const{ return 2*x; }
}
And thus I guess I would have to use a std::vector<Generic*>, and create and destroy the objects dynamically.
A friend suggested me using a std::function<> attribute for my Generic class, and give the specialFunc as an argument to the constructor but I am not sure how to do it properly.
What would be the advantages and drawbacks of these two approaches, and are there other (better ?) ways to do the same thing ? I'm quite curious about it.
For the details, the specialization of each object I instantiate would be determined at runtime, depending on user input. And I might end up with a lot of these objects (not yet sure how many), so I would like to avoid any unnecessary overhead.
virtual functions and overloading model an is-a relationship while std::function models a has-a relationship.
Which one to use depends on your specific use case.
Using std::function is perhaps more flexible as you can easily modify the functionality without introducing new types.
Performance should not be the main decision point here unless this code is provably (i.e. you measured it) the tight loop bottleneck in your program.
First of all, let's throw performance out the window.
If you use virtual functions, as you stated, you may end up with a lot of classes with the same interface:
class generic {
virtual f(float x);
};
class spec1 : public generic {
virtual f(float x);
};
class spec2 : public generic {
virtual f(float x);
};
Using std::function<void(float)> as a member would allow you to avoid all the specializations:
class meaningful_class_name {
std::function<void(float)> f;
public:
meaningful_class_name(std::function<void(float)> const& p_f) : f(p_f) {}
};
In fact, if this is the ONLY thing you're using the class for, you might as well just remove it, and use a std::function<void(float)> at the level of the caller.
Advantages of std::function:
1) Less code (1 class for N functions, whereas the virtual method requires N classes for N functions. I'm making the assumption that this function is the only thing that's going to differ between classes).
2) Much more flexibility (You can pass in capturing lambdas that hold state if you want to).
3) If you write the class as a template, you could use it for all kinds of function signatures if needed.
Using std::function solves whatever problem you're attempting to tackle with virtual functions, and it seems to do it better. However, I'm not going to assert that std::function will always be better than a bunch of virtual functions in several classes. Sometimes, these functions have to be private and virtual because their implementation has nothing to do with any outside callers, so flexibility is NOT an advantage.
Disadvantages of std::function:
1) I was about to write that you can't access the private members of the generic class, but then I realized that you can modify the std::function in the class itself with a capturing lambda that holds this. Given the way you outlined the class however, this shouldn't be a problem since it seems to be oblivious to any sort of internal state.
What would be the advantages and drawbacks of these two approaches, and are there other (better ?) ways to do the same thing ?
The issue I can see is "how do you want your class defined?" (as in, what is the public interface?)
Consider creating an API like this:
class Generic
{
// all other members and attributes
explicit Generic(std::function<float(float)> specialFunc);
};
Now, you can create any instance of Generic, without care. If you have no idea what you will place in specialFunc, this is the best alternative ("you have no idea" means that clients of your code may decide in one month to place a function from another library there, an identical function ("receive x, return x"), accessing some database for the value, passing a stateful functor into your function, or whatever else).
Also, if the specialFunc can change for an existing instance (i.e. create instance with specialFunc, use it, change specialFunc, use it again, etc) you should use this variant.
This variant may be imposed on your code base by other constraints. (for example, if want to avoid making Generic virtual, or if you need it to be final for other reasons).
If (on the other hand) your specialFunc can only be a choice from a limited number of implementations, and client code cannot decide later they want something else - i.e. you only have identical function and doubling the value - like in your example - then you should rely on specializations, like in the code in your question.
TLDR: Decide based on the usage scenarios of your class.
Edit: regarding beter (or at least alternative) ways to do this ... You could inject the specialFunc in your class on an "per needed" basis:
That is, instead of this:
class Generic
{
public:
Generic(std::function<float(float> f) : specialFunc{f} {}
void fancy_computation2() { 2 * specialFunc(2.); }
void fancy_computation4() { 4 * specialFunc(4.); }
private:
std::function<float(float> specialFunc;
};
You could write this:
class Generic
{
public:
Generic() {}
void fancy_computation2(std::function<float(float> f) { 2 * f(2.); }
void fancy_computation4(std::function<float(float> f) { 4 * f(4.); }
private:
};
This offers you more flexibility (you can use different special functions with single instance), at the cost of more complicated client code. This may also be a level of flexibility that you do not want (too much).
Related
I am wrapping a library which I did not write to make it more user friendly. There are a huge number of functions which are very basic so it's not ideal to have to wrap all of these when all that is really required is type conversion of the results.
A contrived example:
Say the library has a class QueryService, it has among others this method:
WeirdInt getId() const;
I'd like a standard int in my interface however, I can get an int out of WeirdInt no problem as I know how to do this. In this case lets say that WeirdInt has:
int getValue() const;
This is a very simple example, often the type conversion is more complicated and not always just a call to getValue().
There are literally hundreds of function calls that return types likes these and more are added all the time, so I'd like to try and reduce the burden on myself having to constantly add a bajillion methods every time the library does just to turn WeirdType into type.
I want to end up with a QueryServiceWrapper which has all the same functionality as QueryService, but where I've converted the types. Am I going to have to write an identically names method to wrap every method in QueryService? Or is there some magic I'm missing? There is a bit more to it as well, but not relevant to this question.
Thanks
The first approach I'd think is by trying with templates such that
you provide a standard implementation for all the wrapper types which have a trivial getValue() method
you specialize the template for all the others
Something like:
class WeirdInt
{
int v;
public:
WeirdInt(int v) : v(v) { }
int getValue() { return v; }
};
class ComplexInt
{
int v;
public:
ComplexInt(int v) : v(v) { }
int getValue() { return v; }
};
template<typename A, typename B>
A wrap(B type)
{
return type.getValue();
}
template<>
int wrap(ComplexInt type)
{
int v = type.getValue();
return v*2;
};
int x = wrap<int, WeirdInt>(WeirdInt(5));
int y = wrap<int, ComplexInt>(ComplexInt(10));
If the wrapper methods for QueryService have a simple pattern, you could also think of generating QueryServiceWrapper with some perl or python script, using some heuristics. Then you need to define some input parameters at most.
Even defining some macros would help in writing this wrapper class.
Briefly, If your aim is to encapsulate the functionality completely so that WeirdInt and QueryService are not exposed to the 'client' code such that you don't need to include any headers which declare them in the client code, then I doubt the approach you take will be able to benefit from any magic.
When I've done this before, my first step has been to use the pimpl idiom so that your header contains no implementation details as follows:
QueryServiceWrapper.h
class QueryServiceWrapperImpl;
class QueryServiceWrapper
{
public:
QueryServiceWrapper();
virtual ~QueryServiceWrapper();
int getId();
private:
QueryServiceWrapperImpl impl_;
};
and then in the definition, you can put the implementation details, safe in the knowledge that it will not leach out to any downstream code:
QueryServiceWrapper.cpp
struct QueryServiceWrapperImpl
{
public:
QueryService svc_;
};
// ...
int QueryServiceWrapper::getValue()
{
return impl_->svc_.getId().getValue();
}
Without knowing what different methods need to be employed to do the conversion, it's difficult add too much more here, but you could certainly use template functions to do conversion of the most popular types.
The downside here is that you'd have to implement everything yourself. This could be a double edged sword as it's then possible to implement only that functionality that you really need. There's generally no point in wrapping functionality that is never used.
I don't know of a 'silver bullet' that will implement the functions - or even empty wrappers on the functions. I've normally done this by a combination of shell scripts to either create the empty classes that I want or taking a copy of the header and using text manipulation using sed or Perl to change original types to the new types for the wrapper class.
It's tempting in these cases to use public inheritance to enable access to the base functions while allowing functions to be overridden. However, this is not applicable in your case as you want to change return types (not sufficient for an overload) and (presumably) you want to prevent exposure of the original Weird types.
The way forward here has to be to use aggregation although in such as case there is no way you can easily avoid re-implementing (some of) the interfaces unless you are prepared to automate the creation of the class (using code generation) to some extent.
more complex approach is to introduce a required number of facade classes over original QueryService, each of which has a limited set of functions for one particular query or query-type. I don't know that your particular QueryService do, so here is an imaginary example:
suppose the original class have a lot of weired methods worked with strange types
struct OriginQueryService
{
WeirdType1 query_for_smth(...);
WeirdType1 smth_related(...);
WeirdType2 another_query(...);
void smth_related_to_another_query(...);
// and so on (a lot of other function-members)
};
then you may write some facade classes like this:
struct QueryFacade
{
OriginQueryService& m_instance;
QueryFacade(OriginQueryService* qs) : m_instance(*qs) {}
// Wrap original query_for_smth(), possible w/ changed type of
// parameters (if you'd like to convert 'em from C++ native types to
// some WeirdTypeX)...
DesiredType1 query_for_smth(...);
// more wrappers related to this particular query/task
DesiredType1 smth_related(...);
};
struct AnotherQueryFacade
{
OriginQueryService& m_instance;
AnotherQueryFacade(OriginQueryService* qs) : m_instance(*qs) {}
DesiredType2 another_query(...);
void smth_related_to_another_query(...);
};
every method delegate call to m_instance and decorated w/ input/output types conversion in a way you want it. Types conversion can be implemented as #Jack describe in his post. Or you can provide a set of free functions in your namespace (like Desired fromWeird(const Weired&); and Weired toWeired(const Desired&);) which would be choosen by ADL, so if some new type arise, all that you have to do is to provide overloads for this 2 functions... such approach work quite well in boost::serialization.
Also you may provide a generic (template) version for that functions, which would call getValue() for example, in case if lot of your Weired types has such member.
I have a simple, low-level container class that is used by a more high-level file class. Basically, the file class uses the container to store modifications locally before saving a final version to an actual file. Some of the methods, therefore, carry directly over from the container class to the file class. (For example, Resize().)
I've just been defining the methods in the file class to call their container class variants. For example:
void FileClass::Foo()
{
ContainerMember.Foo();
}
This is, however, growing to be a nuisance. Is there a better way to do this?
Here's a simplified example:
class MyContainer
{
// ...
public:
void Foo()
{
// This function directly handles the object's
// member variables.
}
}
class MyClass
{
MyContainer Member;
public:
void Foo()
{
Member.Foo();
// This seems to be pointless re-implementation, and it's
// inconvenient to keep MyContainer's methods and MyClass's
// wrappers for those methods synchronized.
}
}
Well, why not just inherit privatly from MyContainer and expose those functions that you want to just forward with a using declaration? That is called "Implementing MyClass in terms of MyContainer.
class MyContainer
{
public:
void Foo()
{
// This function directly handles the object's
// member variables.
}
void Bar(){
// ...
}
}
class MyClass : private MyContainer
{
public:
using MyContainer::Foo;
// would hide MyContainer::Bar
void Bar(){
// ...
MyContainer::Bar();
// ...
}
}
Now the "outside" will be able to directly call Foo, while Bar is only accessible inside of MyClass. If you now make a function with the same name, it hides the base function and you can wrap base functions like that. Of course, you now need to fully qualify the call to the base function, or you'll go into an endless recursion.
Additionally, if you want to allow (non-polymorphical) subclassing of MyClass, than this is one of the rare places, were protected inheritence is actually useful:
class MyClass : protected MyContainer{
// all stays the same, subclasses are also allowed to call the MyContainer functions
};
Non-polymorphical if your MyClass has no virtual destructor.
Yes, maintaining a proxy class like this is very annoying. Your IDE might have some tools to make it a little easier. Or you might be able to download an IDE add-on.
But it isn't usually very difficult unless you need to support dozens of functions and overrides and templates.
I usually write them like:
void Foo() { return Member.Foo(); }
int Bar(int x) { return Member.Bar(x); }
It's nice and symmetrical. C++ lets you return void values in void functions because that makes templates work better. But you can use the same thing to make other code prettier.
That's delegation inheritance and I don't know that C++ offers any mechanism to help with that.
Consider what makes sense in your case - composition (has a) or inheritance (is a) relationship between MyClass and MyContainer.
If you don't want to have code like this anymore, you are pretty much restricted to implementation inheritance (MyContainer as a base/abstract base class). However you have to make sure this actually makes sense in your application, and you are not inheriting purely for the implementation (inheritance for implementation is bad).
If in doubt, what you have is probably fine.
EDIT: I'm more used to thinking in Java/C# and overlooked the fact that C++ has the greater inheritance flexibility Xeo utilizes in his answer. That just feels like nice solution in this case.
This feature that you need to write large amounts of code is actually necessary feature. C++ is verbose language, and if you try to avoid writing code with c++, your design will never be very good.
But the real problem with this question is that the class has no behaviour. It's just a wrapper which does nothing. Every class needs to do something other than just pass data around.
The key thing is that every class has correct interface. This requirement makes it necessary to write forwarding functions. The main purpose of each member function is to distribute the work required to all data members. If you only have one data member, and you've not decided yet what the class is supposed to do, then all you have is forwarding functions. Once you add more member objects and decide what the class is supposed to do, then your forwarding functions will change to something more reasonable.
One thing which will help with this is to keep your classes small. If the interface is small, each proxy class will only have small interface and the interface will not change very often.
I have two classes that are almost identical, besides one method. The classes have the same data part and all the member functions but one:
class A {
private:
double data;
public:
double calc(){
return data*data;
}
double especific(){
return 2.0*data;
}
}
and the second class is identical, besides the especific method.
This member function in particular needs all the member data to calculate, so passing by value or reference is not an option. Is there a way to implement this without a lot of code duplication? Either using only one class or using templates, but not inheritance (huge performance impact).
Thanks
EDIT: Thanks for all the responses. The Strategy pattern can help in my case, I will try it and see if it works. I'm avoiding virtual inheritance as the plague based on some tests that I did in a different program. This routine will be called everywhere, and performance is a very important factor.
This sounds like a job for the Strategy pattern. It can be implemented in this case as a template parameter. Often it would be implemented as a constructor parameter or a setter method on the class, but that would require inheritance to work properly.
In this case, something like:
template <class SpecificStrategy>
class A {
private:
double data;
public:
double calc(){
return data*data;
}
double especific() {
return SpecificStrategy::especific(data);
}
};
class DoubleStrategy {
static double especific(double data) {
return 2 * data;
}
};
class TripleStrategy {
static double especific(double data) {
return 3 * data;
}
};
Then you can refer to:
A<DoubleStrategy> x;
A<TripleStrategy> y;
x and y will be of completely unrelated types, but it sounds like that's not what you want in this case.
Now, in my opinion using a virtual function and inheritance is the way to go. As someone else pointed out, the performance penalty isn't that large. However there are circumstances in which I could see that it would be a bad idea.
For example, if this class is intended to represent a vector in a graphics package and you're going to be doing the same transform to millions of them, then I could see how you would not want a virtual function call to be a part of the code that did the transform. In fact, you would want to avoid pointer dereferences of any kind of you could at all help it.
Maybe I'm missing the point but why not have a base class that implements all the common functionality and a pure virtual especific() and then inherit this and have the child classes implement especific() as required. Make the data member protected.
class BaseA
{
protected:
double data;
public:
double calc(){
return data*data;
}
virtual double especific() = 0;
};
class A1 : BaseA
{
double especific()
{
return data * 2;
}
};
WRT to the huge performance impact of inheritance... I think this isn't likely unless the cost of vtable lookups is significant compared with the work being done in the method body and you're doing this in a tight loop what's consuming most of your application processing.
If you don't make any members virtual and define your classes intelligently there should be no performance impact whatsoever from inheritence.
All inheritence is saying is "make this class like that one, but with this extra stuff". It is no different at runtime than if you'd typed the same stuff twice.
I suppose you could make a performance impact by doing a bunch of unnesscary stuff in the constructor for the parent class that the child classes don't need. But you won't be that stupid. I have faith in you.
Why two classes at all? If the classes share the same data, you may just want to implement both functions in one class.
class A {
private:
double data;
public:
double calc(){
return data*data;
}
double especific(){
return 2.0*data;
}
double eMoreSpecific() {
return 23.0*data;
}
have a base class with all the common stuff and derive the two classes from it
As others have pointed out
a) this is exactly what inheritance was designed for
b) there is no perfomance overhead whatsoever
c) there are no nasty gotchas lurking anywhere
Many people will comment on this and say 'ah but what about xxxx'; these will be valid comments for advanced and corner case use; except you are not going to do any of them based on the simplicity of what you asked for.
Check out the Strategy Pattern
You could have your class take a functor which especific then calls. You can supply different functors for different ways of calculating the output. There are several other ways you can implement Strategy as well.
I have a feeling that a Bridge pattern might be a good approach for you as it sounds like you want to have unique implementations for your common abstraction.
There are several ways to do this, many of which you've named:
Inheritance from a common base class (which does most of the work), and virtual especific()
One class, with two slightly differently-named especific() methods (or overloaded methods)
Use template specialisation
Have A and B use some other class C to do the majority of the work.
There may be others.
You'll need to choose one of these based on the semantics of your classes and application, and any other specific constraints or requirements.
check out the "inheritance pattern"
I'm building an hierarchy of objects that wrap primitive types, e.g integers, booleans, floats etc, as well as container types like vectors, maps and sets. I'm trying to (be able to) build an arbitrary hierarchy of objects, and be able to set/get their values with ease. This hierarchy will be passed to another class (not mentioned here) and an interface will be created from this representation. This is the purpose of this hierarchy, to be able to create a GUI representation from these objects.To be more precise, i have something like this:
class ValObject
{
public:
virtual ~ValObject() {}
};
class Int : public ValObject
{
public:
Int(int v) : val(v) {}
void set_int(int v) { val = v);
int get_int() const { return val; }
private:
int val;
};
// other classes for floats, booleans, strings, etc
// ...
class Map : public ValObject {}
{
public:
void set_val_for_key(const string& key, ValObject* val);
ValObject* val_for_key(const string& key);
private:
map<string, ValObject*> keyvals;
};
// classes for other containers (vector and set) ...
The client, should be able to create and arbitrary hierarchy of objects, set and get their values with ease, and I, as a junior programmer, should learn how to correctly create the classes for something like this.
The main problem I'm facing is how to set/get the values through a pointer to the base class ValObject. At first, i thought i could just create lots of functions in the base class, like set_int, get_int, set_string, get_string, set_value_for_key, get_value_for_key, etc, and make them work only for the correct types. But then, i would have lots of cases where functions do nothing and just pollute my interface. My second thought was to create various proxy objects for setting and getting the various values, e.g
class ValObject
{
public:
virtual ~ValObject() {}
virtual IntProxy* create_int_proxy(); // <-- my proxy
};
class Int : public ValObject
{
public:
Int (int v) : val(v) {}
IntProxy* create_int_proxy() { return new IntProxy(&val); }
private:
int val;
};
class String : public ValObject
{
public:
String(const string& s) : val(s) {}
IntProxy* create_int_proxy() { return 0; }
private:
string val;
};
The client could then use this proxy to set and get the values of an Int through an ValObject:
ValObject *val = ... // some object
IntProxy *ipr = val->create_int_proxy();
assert(ipr); // we know that val is an Int (somehow)
ipr->set_val(17);
But with this design, i still have too many classes to declare and implement in the various subclasses. Is this the correct way to go ? Are there any alternatives ?
Thank you.
Take a look at boost::any and boost::variant for existing solutions. The closest to what you propose is boost::any, and the code is simple enough to read and understand even if you want to build your own solution for learning purposes --if you need the code, don't reinvent the wheel, use boost::any.
One of the beauties of C++ is that these kinds of intrusive solutions often aren't necessary, yet unfortunately we still see similar ones being implemented today. This is probably due to the prevalence of Java, .NET, and QT which follows these kinds of models where we have a general object base class which is inherited by almost everything.
By intrusive, what's meant is that the types being used have to be modified to work with the aggregate system (inheriting from a base object in this case). One of the problems with intrusive solutions (though sometimes appropriate) is that they require coupling these types with the system used to aggregate them: the types become dependent on the system. For PODs it is impossible to use intrusive solutions directly as we cannot change the interface of an int, e.g.: a wrapper becomes necessary. This is also true of types outside your control like the standard C++ library or boost. The result is that you end up spending a lot of time and effort manually creating wrappers to all kinds of things when such wrappers could have been easily generated in C++. It can also be very pessimistic on your code if the intrusive solution is uniformly applied even in cases where unnecessary and incurs a runtime/memory overhead.
With C++, a plethora of non-intrusive solutions are available at your fingertips, but this is especially true when we know that we can combine static polymorphism using templates with dynamic polymorphism using virtual functions. Basically we can generate these base object-derived wrappers with virtual functions on the fly only for the cases in which this solution is needed without pessimizing the cases where this isn't necessary.
As already suggested, boost::any is a great model for what you want to achieve. If you can use it directly, you should use it. If you can't (ex: if you are providing an SDK and cannot depend on third parties to have matching versions of boost), then look at the solution as a working example.
The basic idea of boost::any is to do something similar to what you are doing, only these wrappers are generated at compile-time. If you want to store an int in boost::any, the class will generate an int wrapper class which inherits from a base object that provides the virtual interface required to make any work at runtime.
The main problem I'm facing is how to
set/get the values through a pointer
to the base class ValObject. At first,
i thought i could just create lots of
functions in the base class, like
set_int, get_int, set_string,
get_string, set_value_for_key,
get_value_for_key, etc, and make them
work only for the correct types. But
then, i would have lots of cases where
functions do nothing and just pollute
my interface.
As you already correctly deduced, this would generally be an inferior design. One tell-tale sign of inheritance being used improperly is when you have a lot of base functions which are not applicable to your subclasses.
Consider the design of I/O streams. We don't have ostreams with functions like output_int, output_float, output_foo, etc. as being directly methods in ostream. Instead, we can overload operator<< to output any data type we want in a non-intrusive fashion. A similar solution can be achieved for your base type. Do you want to associate widgets with custom types (ex: custom property editor)? We can allow that:
shared_ptr<Widget> create_widget(const shared_ptr<int>& val);
shared_ptr<Widget> create_widget(const shared_ptr<float>& val);
shared_ptr<Widget> create_widget(const shared_ptr<Foo>& val);
// etc.
Do you want to serialize these objects? We can use a solution like I/O streams. If you are adapting your own solution like boost::any, it can expect such auxiliary functions to already be there with the type being stored (the virtual functions in the generated wrapper class can call create_widget(T), e.g.
If you cannot be this general, then provide some means of identifying the types being stored (a type ID, e.g.) and handle the getting/setting of various types appropriately in the client code based on this type ID. This way the client can see what's being stored and deal set/get values on it accordingly.
Anyway, it's up to you, but do consider a non-intrusive approach to this as it will generally be less problematic and a whole lot more flexible.
Use dynamic_cast to cast up the hierarchy. You don't need to provide an explicit interface for this - any reasonable C++ programmer can do that. If they can't do that, you could try enumerating the different types and creating an integral constant for each, which you can then provide a virtual function to return, and you can then static_cast up.
Finally, you could consider passing a function object, in double-dispatch style. This has a definite encapsulation advantage.
struct functor {
void operator()(Int& integral) {
...
}
void operator()(Bool& boo) {
...
}
};
template<typename Functor> void PerformOperationByFunctor(Functor func) {
if (Int* ptr = dynamic_cast<Int*>(this)) {
func(*ptr);
}
// Repeat
}
More finally, you should avoid creating types where they've basically been already covered. For example, there's little point providing a 64bit integral type and a 32bit integral type and ... it's just not worth the hassle. Same with double and float.
When implementing polymorphic behavior in C++ one can either use a pure virtual method or one can use function pointers (or functors). For example an asynchronous callback can be implemented by:
Approach 1
class Callback
{
public:
Callback();
~Callback();
void go();
protected:
virtual void doGo() = 0;
};
//Constructor and Destructor
void Callback::go()
{
doGo();
}
So to use the callback here, you would need to override the doGo() method to call whatever function you want
Approach 2
typedef void (CallbackFunction*)(void*)
class Callback
{
public:
Callback(CallbackFunction* func, void* param);
~Callback();
void go();
private:
CallbackFunction* iFunc;
void* iParam;
};
Callback::Callback(CallbackFunction* func, void* param) :
iFunc(func),
iParam(param)
{}
//Destructor
void go()
{
(*iFunc)(iParam);
}
To use the callback method here you will need to create a function pointer to be called by the Callback object.
Approach 3
[This was added to the question by me (Andreas); it wasn't written by the original poster]
template <typename T>
class Callback
{
public:
Callback() {}
~Callback() {}
void go() {
T t; t();
}
};
class CallbackTest
{
public:
void operator()() { cout << "Test"; }
};
int main()
{
Callback<CallbackTest> test;
test.go();
}
What are the advantages and disadvantages of each implementation?
Approach 1 (Virtual Function)
"+" The "correct way to do it in C++
"-" A new class must be created per callback
"-" Performance-wise an additional dereference through VF-Table compared to Function Pointer. Two indirect references compared to Functor solution.
Approach 2 (Class with Function Pointer)
"+" Can wrap a C-style function for C++ Callback Class
"+" Callback function can be changed after callback object is created
"-" Requires an indirect call. May be slower than functor method for callbacks that can be statically computed at compile-time.
Approach 3 (Class calling T functor)
"+" Possibly the fastest way to do it. No indirect call overhead and may be inlined completely.
"-" Requires an additional Functor class to be defined.
"-" Requires that callback is statically declared at compile-time.
FWIW, Function Pointers are not the same as Functors. Functors (in C++) are classes that are used to provide a function call which is typically operator().
Here is an example functor as well as a template function which utilizes a functor argument:
class TFunctor
{
public:
void operator()(const char *charstring)
{
printf(charstring);
}
};
template<class T> void CallFunctor(T& functor_arg,const char *charstring)
{
functor_arg(charstring);
};
int main()
{
TFunctor foo;
CallFunctor(foo,"hello world\n");
}
From a performance perspective, Virtual functions and Function Pointers both result in an indirect function call (i.e. through a register) although virtual functions require an additional load of the VFTABLE pointer prior to loading the function pointer. Using Functors (with a non-virtual call) as a callback are the highest performing method to use a parameter to template functions because they can be inlined and even if not inlined, do not generate an indirect call.
Approach 1
Easier to read and understand
Less possibility of errors (iFunc cannot be NULL, you're not using a void *iParam, etc
C++ programmers will tell you that this is the "right" way to do it in C++
Approach 2
Slightly less typing to do
VERY slightly faster (calling a virtual method has some overhead, usually the same of two simple arithmetic operations.. So it most likely won't matter)
That's how you would do it in C
Approach 3
Probably the best way to do it when possible. It will have the best performance, it will be type safe, and it's easy to understand (it's the method used by the STL).
The primary problem with Approach 2 is that it simply doesn't scale. Consider the equivalent for 100 functions:
class MahClass {
// 100 pointers of various types
public:
MahClass() { // set all 100 pointers }
MahClass(const MahClass& other) {
// copy all 100 function pointers
}
};
The size of MahClass has ballooned, and the time to construct it has also significantly increased. Virtual functions, however, are O(1) increase in the size of the class and the time to construct it- not to mention that you, the user, must write all the callbacks for all the derived classes manually which adjust the pointer to become a pointer to derived, and must specify function pointer types and what a mess. Not to mention the idea that you might forget one, or set it to NULL or something equally stupid but totally going to happen because you're writing 30 classes this way and violating DRY like a parasitic wasp violates a caterpillar.
Approach 3 is only usable when the desired callback is statically knowable.
This leaves Approach 1 as the only usable approach when dynamic method invocation is required.
It's not clear from your example if you're creating a utility class or not. Is you Callback class intended to implement a closure or a more substantial object that you just didn't flesh out?
The first form:
Is easier to read and understand,
Is far easier to extend: try adding methods pause, resume and stop.
Is better at handling encapsulation (presuming doGo is defined in the class).
Is probably a better abstraction, so easier to maintain.
The second form:
Can be used with different methods for doGo, so it's more than just polymorphic.
Could allow (with additional methods) changing the doGo method at run-time, allowing the instances of the object to mutate their functionality after creation.
Ultimately, IMO, the first form is better for all normal cases. The second has some interesting capabilities, though -- but not ones you'll need often.
One major advantage of the first method is it has more type safety. The second method uses a void * for iParam so the compiler will not be able to diagnose type problems.
A minor advantage of the second method is that it would be less work to integrate with C. But if you're code base is only C++, this advantage is moot.
Function pointers are more C-style I would say. Mainly because in order to use them you usually must define a flat function with the same exact signature as your pointer definition.
When I write C++ the only flat function I write is int main(). Everything else is a class object. Out of the two choices I would choose to define an class and override your virtual, but if all you want is to notify some code that some action happened in your class, neither of these choices would be the best solution.
I am unaware of your exact situation but you might want to peruse design patterns
I would suggest the observer pattern. It is what I use when I need to monitor a class or wait for some sort of notification.
For example, let us look at an interface for adding read functionality to a class:
struct Read_Via_Inheritance
{
virtual void read_members(void) = 0;
};
Any time I want to add another source of reading, I have to inherit from the class and add a specific method:
struct Read_Inherited_From_Cin
: public Read_Via_Inheritance
{
void read_members(void)
{
cin >> member;
}
};
If I want to read from a file, database, or USB, this requires 3 more separate classes. The combinations start to be come very ugly with multiple objects and multiple sources.
If I use a functor, which happens to resemble the Visitor design pattern:
struct Reader_Visitor_Interface
{
virtual void read(unsigned int& member) = 0;
virtual void read(std::string& member) = 0;
};
struct Read_Client
{
void read_members(Reader_Interface & reader)
{
reader.read(x);
reader.read(text);
return;
}
unsigned int x;
std::string& text;
};
With the above foundation, objects can read from different sources just by supplying different readers to the read_members method:
struct Read_From_Cin
: Reader_Visitor_Interface
{
void read(unsigned int& value)
{
cin>>value;
}
void read(std::string& value)
{
getline(cin, value);
}
};
I don't have to change any of the object's code (a good thing because it is already working). I can also apply the reader to other objects.
Generally, I use inheritance when I am performing generic programming. For example, if I have a Field class, then I can create Field_Boolean, Field_Text and Field_Integer. In can put pointers to their instances into a vector<Field *> and call it a record. The record can perform generic operations on the fields, and doesn't care or know what kind of a field is processed.
Change to pure virtual, first off. Then inline it. That should negate any method overhead call at all, so long as inlining doesn't fail (and it won't if you force it).
May as well use C, because this is the only real useful major feature of C++ compared to C. You will always call method and it can't be inlined, so it will be less efficient.