Sign in to follow this  
Spynacker

C++ Memberfunction-pointers in inheritance

Recommended Posts

Spynacker    106
Hey guys this is my first question to this forum and it is a hard one for me. I want to implement some function pointers. Here is the class structure:
class A{
  virtual void function()=0;
public:
  void (A::*func_ptr)();
};

class B:public A{
  virtual void function();
public:
  B();
};
//Several other classes that inherit A and will override function()

B::B()
:func_ptr(&B::function)
{}

The problem is that the compiler says:
cannot convert 'void (B::*)()' to 'void (A::*)()' in assignment
So I can not initialize the member func_ptr of B with this functionpointer. Is there any possible way to manage this? I guess forcing a cast could result in major problems as memberfunctions are treated differently. I want to use this pointers rather than inheritance overriding because of the overhead. It is used in a very high performance code. I hope there is someone out there who can solve my problem. Thanks for reading, I am looking forward for your answers.

Share this post


Link to post
Share on other sites
Bregma    9214
The C++ language does not support contravariance. You can not do what you are trying to do. My experience is that if the language does not support you trying to do something wacky, it's your design that's broken not the language.

Can you post your performance analysis numbers showing that dereferencing pointers to member functions is faster than using virtual functions? I would be very interested in seeing this.

Share this post


Link to post
Share on other sites
Antheus    2409
Quote:
Original post by Spynacker
I want to use this pointers rather than inheritance overriding because of
the overhead. It is used in a very high performance code.


If it's "high performance" code, then polymorphism is the wrong choice anyway.

If complete support of polymorphic types is required, then there is boost::function.

Quote:
B::B()
:func_ptr(&B::function)

If function is polymorphic, then func_ptr(&A::function) does exactly the same thing.

Share this post


Link to post
Share on other sites
Decrius    100
I didn't know inheritance had such a performance impact...

I guess you could either perform a static_cast (but there is much likely some undefined behaviour here...), or use templates:

template <class T>
class A
{
public:
A(T *i_ptr, void (T::*i_func_ptr)());

virtual void function() = 0;

private:
T *m_ptr;
void (T::*m_func_ptr)();
};

class B: public A<B>
{
public:
B();

void function();
};

template <class T>
A<T>::A(T *i_ptr, void (T::*i_func_ptr)()) :
m_ptr(i_ptr),
m_func_ptr(i_func_ptr)
{
(m_ptr->*m_func_ptr)(); // crash: pure virtual method called
}

B::B() :
A<B>(this, &B::function)
{
}

void B::function()
{
std::cout << "function invoked\n";
}


I have no idea why this crashes, I guess you should even be able to get away with not passing the 'this' pointer...it's not working but it gives you a clue (maybe someone else knows what is wrong?).

Also, if this is only to avoid inheritance...is that even worth it?

Share this post


Link to post
Share on other sites
rip-off    10979
Quote:

I have no idea why this crashes, I guess you should even be able to get away with not passing the 'this' pointer...it's not working but it gives you a clue (maybe someone else knows what is wrong?).

You are calling a virtual function of an imcompletely constructed object.

Quote:

I didn't know inheritance had such a performance impact...

It depends on what you are doing and how you are measuring. Typically, inheritance is free - but virtual functions incur a small overhead for dynamic dispatch.

Ideally the amount of work done in the method would easily amortise the cost of the virtual function. If not, this might hint that your design needs work.

@Spynacker: can you give us a high level overview of what you are doing? High performance is typically achieved with macro optimisations first, only later moving down to micro optimisations if the performance criteria have not been met.

Share this post


Link to post
Share on other sites
Decrius    100
Quote:
Original post by rip-off
You are calling a virtual function of an imcompletely constructed object.


Heh yeah, now I see it too...lame ^_^

Quote:

It depends on what you are doing and how you are measuring. Typically, inheritance is free - but virtual functions incur a small overhead for dynamic dispatch.


True, but the cost of dynamic dispatching is really really low. And I think it greatly out weights the advantages over the tiny bit of real time cost (unless you really have a vast amount of virtual functions..).

Share this post


Link to post
Share on other sites
Spynacker    106
Thanks for the posts so far folks.
To make things a bit more clear let me explain some
more details.
I have about 10 different subclasses of A that all will
implement their own version of function. There will be a
lot of instances of all these subclasses that are handled
as objects of A in a std::list<A*>. All of these hundreds of
instances will get called with function() thousands of times
so every little bit of performance increase will help.

To answer some of your statements:
This "high-performance code" should not be written in low-level design.
I brought it to live in a very beautiful class design and then began to
increase performance by adding assemblerparts and restructuring the code.
Now I am at the point that my structure itself prevents further increase
if I let the class structure be.
For the sake of beeing able to easily expand my project I do not want to
tear the classes down but I need some change in there.

Maybe I will look for Boost but for now I am considering to reject the
subclasses of A and put every special function into a. That would be an
awful step back but with my eyes looking forward to further actions this
could be the best solution.

I would appriciate other opinions and advices.

Share this post


Link to post
Share on other sites
SiCrane    11839
Be very careful before you decide to place additional data members in a class to speed up a computation. It's entirely possible that additional data member will actually slow down the computation by increasing class size and thus giving you worse cache coherency. I've done an informal study comparing dispatch methods for classes, and it's really hard to beat normal virtual functions in the normal case where you want to do something different for each derived class.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this