1
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

Community
  • 1
  • 1
Scott Oliver
  • 507
  • 5
  • 19
  • 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 Apr 01 '14 at 06:06
  • 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](http://coliru.stacked-crooked.com/a/86071a262c7caef1)). – WhozCraig Apr 01 '14 at 06:14
  • 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, @WhozCraig – Scott Oliver Apr 01 '14 at 08:42
  • 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 Apr 01 '14 at 10:15

1 Answers1

0

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()
WhozCraig
  • 65,258
  • 11
  • 75
  • 141