1
votes
class Base
{
    virtual void Foo(){}
    virtual void Bar(){}
};

class Derived1 : public Base
{
    void Foo(){ //Do something }
    void Bar(){ //Do something }
}

class Derived2 : public Base
{
    void Foo(){ //Do something }
    void Bar(){ //Do something }
}

class OtherClass
{
public:
    Base* obj;
    void (Base::*method)();

    void Add( Base* _obj, void (Base::*_method)() )
    {
        obj = _obj;
        method = _method;
    }

    void Run()
    {
        ( obj->method )();
    }
}

int main()
{
    Derived1 d1;
    Derived2 d2;

    OtherClass other;

    other.Add( &d1, &(Derived1::Foo) );
    //other.Add( &d2, &(Derived2::Bar) ); etc, etc.

    other.Run();
}

My question:

Say I have a derived class with a method, I can refer to an instance of that class with a pointer of it's base type. Assuming I know what method I want to call, I can then call it via that pointer and the derived class's method will be called.

How can I achieve similar polymorphic behaviour when I specify the method to be called by supplying a method pointer?

The real code the above is based on will compile if I cast the method pointer, but it appears to not be doing any-- It is at this point I've realised I wasn't calling OtherClass's update method, which is why I wasn't getting any joy. :D So this works, as is (almost). Stupid, stupid brain.

Slight course correction then: Right now I need to static cast the method pointer I pass to OtherClass, to a pointer to Base class method when I pass it to Add. This is not ideal.

Can I get the same behaviour if I pass &(Base::Foo), for example, to the method Add?

Will Derived1::Foo be called if I invoke that method on a pointer to base type that refers to an instance of the derived type?

I get the feeling it'll call the base member. :(

Some reading: Is it safe to "upcast" a method pointer and use it with base class pointer? C++ inheritance and member function pointers Pointer to member conversion Casting a pointer to a method of a derived class to a pointer to a method of a base class

1
Something tells me most of your question could be answered by actually doing something (like sending a msg to stdout) in your members of your posted code rather than ending them with their closing curly braces buried in a single line comment.WhozCraig
And don't static cast the pointer. just pass the base class method pointer. The derived member will be fired if the virtual inheritance is setup correctly (and in this case, it is).WhozCraig
I was initially looking for a different answer but solved my own problem midway through, decided to change the question, so I understand why you posted that comment but at the time my real code was doing something and nothing was happening. I probably could have answered the new question with a bit of experimentation but I was heading for work and had already typed out most of the post. :) Plus, I thought it would be worth having on the site. Your second comment is great though, and that's a neat tool. Post it as an answer and I'll mark it, @WhozCraigScott Oliver
Oh good then. I didn't post it as an answer because I wasn't sure that was what you were looking toward. i.e. will passing a member-fn-ptr of a virtual base member fire the appropriate derived member. I was hoping that was where you were going. And yeah, both Coliru and Ideone are outstanding for off-the cuff code snips. Both are often used here.WhozCraig

1 Answers

0
votes

i believe you're pondering whether a member-fn-ptr of a virtual base will fire the polymorphic derivation override if provided in a derived class. If so, the answer is yes, and the code below demonstrate this.

Hope this helps.

#include <iostream>

class Base
{
public:
    virtual void Foo()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
    virtual void Bar()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

class Derived1 : public Base
{
public:
    void Foo()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }

    void Bar()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

class Derived2 : public Base
{
public:
    void Foo()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }

    void Bar()
    {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }
};

class OtherClass
{
public:
    Base* obj;
    void (Base::*method)();

    void Add( Base* _obj, void (Base::*_method)() )
    {
        obj = _obj;
        method = _method;
    }

    void Run()
    {
        (obj->*method)();
    }
};

int main()
{
    Derived1 d1;
    Derived2 d2;

    OtherClass other;

    other.Add( &d1, &Base::Foo );
    other.Run();

    other.Add( &d2, &Base::Bar);
    other.Run();
}

Output

virtual void Derived1::Foo()
virtual void Derived2::Bar()