Function pointers vs subclasses

Hi Guys,

I am in a position to choose between function pointers and subclassed objects. To make it clear, say I have to notify some object of some action (a timer for example); refer to the following two choices (a very basic code for demo purposes):

Version 1
1
2
3
4
5
6
7
8
typedef void TimerCallback(void *args);
class Timer{
public:
  Timer();
  ~Timer();
  void schedule(TimerCallback *callback, void *args, long timeout)=0;
  void cancel();
};


Version 2:
1
2
3
4
5
6
7
8
9
10
11
12
13
class TimerTask{
  public:
    TimerTask();
    virtual ~TimerTask();
    void timedout()=0;
};
class Timer{
  public:
    Timer();
    virtual ~Timer();
    void schedule(TimerTask *callback, long timeout)=0;
    void cancel();
};


which one is the standard C++ way and which one is efficient?

Please let me know if I am not clear in this regard.

Thanks
Neither. The usual C++ way is to pass a function object (e.g. the result of a bind(), a lambda expression, or a user-defined class with an operator() to call back). They are generally more efficient than function pointers or your callback object with a virtual function call because they are much easier to inline.
Last edited on
> which one is the standard C++ way

The standard C++ way would be to give the users of the timer class complete flexibility in deciding how to implement the callback.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <functional>
#include <vector>
#include <iostream>

struct timer
{
    template < typename FN, typename ... ARGS >
    void schedule( FN fn, ARGS... args )
    {
        callbacks.emplace_back( std::bind( fn, args... ) ) ;
        // ...
    }

    void notify_all() { for( const auto& fn : callbacks ) fn() ; }

    std::vector< std::function< void(void) > > callbacks ;
};

void free_fun( int a, double b ) { std::cout << "free_fun( " << a << ", " << b << " )\n" ; }

int main()
{
    timer t ;

    struct A { int mem_fun() { std::cout << "A::mem_fun()\n" ; return 7 ; } };
    A object ;
    t.schedule( &A::mem_fun, &object ) ;

    t.schedule( [](int i) { std::cout << "closure(" << i << ")\n" ; }, 70 ) ;

    t.schedule( free_fun, 23, 7.89 ) ;

    t.notify_all() ;
}
Last edited on
In the case of a library that needs to be able to be compiled with one compiler and linked to code compiled in another, I don't think virtual inheritance or std::function are acceptable. Function pointers are more universal, unfortunately, but you can always restrict users of your library to compile the library with the same compiler and settings as the code they're linking to.
> In the case of a library that needs to be able to be compiled with one compiler
> and linked to code compiled in another, ...

Do not use C++. Any part of C++.
JLBorges wrote:
Do not use C++. Any part of C++.
Oh, I guess that makes sense. I've got to pick a side. I'll choose to not allow cross-linking in that case.
Are there C++ libraries that aren't templated on callback type? Even ACE did that.
Topic archived. No new replies allowed.