Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting function pointers in C++

Suppose I have two classes, A and B:

class A
{
public:
    typedef void (*Handler)( A * a );

    Handler handler;

    void foo() ( handler( this ); }
};

class B : public A
{
};

Suppose I have a function

void bar( B * b );

Can I then go

B b;
b.handler = bar;???

If I declare void bar( A * a ) then all is cool, but then I have to cast a to a B* which is ugly. I can't template a typedef, so is there a nice way of doing this?

like image 631
Julian Gold Avatar asked May 09 '26 15:05

Julian Gold


2 Answers

No, there isn't.

You're violating LSP: b.handler() can't be called with any random A*, while the base class promisses it can.

B b;
b.handler = bar; // This doesn't compile!
A a2;
b.handler(&a2); // As this would call bar(B*) with an A*

It is possible to have a different type in cases like this, but only when arguments are contra-variant and return values co-variant.

like image 141
Sjoerd Avatar answered May 11 '26 05:05

Sjoerd


This is the solution mentioned by cdhowie. You can define an abstract base class:

template<typename T>
class AbstractA {
   typedef void (*Handler)( T * a );
   Handler handler;

   void foo() ( handler( (T*) this ); }
};

And then implement child classes like this:

class A : public AbstractA<A> {
    //...
};

class B : public AbstractA<B> {
    //...
};
like image 31
Sebastian Hoffmann Avatar answered May 11 '26 05:05

Sebastian Hoffmann



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!