Pointer-to-member-function pointing to a member function of an inherited class

Discussion in 'C++' started by akiriwas@gmail.com, Jan 29, 2005.

  1. Guest

    The subject basically says what I am having trouble with. For an
    example lets say I have a class A which has a function f. I then also
    have a class B which inherits from A and has a function g.

    class A
    {
    public: void f(int,float);
    };

    class B : public A
    {
    public: void g(int, float);
    };


    Okay, now with all that setup, if I created a pointer to a member
    function something like this:

    typedef void (A::*MFP)(int a, float b);

    if I then use it such as

    MFP mfp = &A::f;

    then everything works fine.

    even if I do:

    MFP mfp2 = &B::f;

    then everything still works (presumably because f is not defined in B
    and must then be from A). However, if I try this:

    MFP mfp3 = &B::g;

    then it complains that B::g is not of the right type since it is not a
    member function of class A. The protype signature is the same, both
    (int, float), is there no way to make this work? It seemed to me that
    it should have worked since any instance of B is still by definition an
    instance of A. Anyone done anything like this?

    -akiriwas
    , Jan 29, 2005
    #1
    1. Advertising

  2. Re: Pointer-to-member-function pointing to a member function of aninherited class

    wrote:
    > The subject basically says what I am having trouble with. For an
    > example lets say I have a class A which has a function f. I then also
    > have a class B which inherits from A and has a function g.
    >
    > class A
    > {
    > public: void f(int,float);
    > };
    >
    > class B : public A
    > {
    > public: void g(int, float);
    > };
    >
    >
    > Okay, now with all that setup, if I created a pointer to a member
    > function something like this:
    >
    > typedef void (A::*MFP)(int a, float b);


    Try making this :

    typedef void (B::*MFP)(int a, float b);

    >
    > if I then use it such as
    >
    > MFP mfp = &A::f;
    >
    > then everything works fine.
    >
    > even if I do:
    >
    > MFP mfp2 = &B::f;


    &B::f becomes &A::f when the compiler is done with it because f is a
    member of A - this is some magic specified by the standard and only
    works with literal pointer to members.

    An A::* member pointer can be converted to a B::* member pointer but not
    the other way. i.e.

    typedef void (A::*AMFP)(int a, float b);
    typedef void (B::*BMFP)(int a, float b);
    void f( AMFP a, AMFP b )
    {
    b = a; // legal
    a = b; // illegal
    }

    >
    > then everything still works (presumably because f is not defined in B
    > and must then be from A). However, if I try this:
    >
    > MFP mfp3 = &B::g;


    Think about it - an object of type A can't really support a method of
    class B since it's impossible to really which type of object you really
    have.

    >
    > then it complains that B::g is not of the right type since it is not a
    > member function of class A. The protype signature is the same, both
    > (int, float), is there no way to make this work? It seemed to me that
    > it should have worked since any instance of B is still by definition an
    > instance of A. Anyone done anything like this?


    Yes.

    options for this case are:

    a) use virtual methods
    b) use functions (not member functions)
    Gianni Mariani, Jan 29, 2005
    #2
    1. Advertising

  3. Mike Wahler Guest

    <> wrote in message
    news:...
    > The subject basically says what I am having trouble with. For an
    > example lets say I have a class A which has a function f. I then also
    > have a class B which inherits from A and has a function g.
    >
    > class A
    > {
    > public: void f(int,float);
    > };
    >
    > class B : public A
    > {
    > public: void g(int, float);
    > };
    >
    >
    > Okay, now with all that setup, if I created a pointer to a member
    > function something like this:
    >
    > typedef void (A::*MFP)(int a, float b);
    >
    > if I then use it such as
    >
    > MFP mfp = &A::f;
    >
    > then everything works fine.
    >
    > even if I do:
    >
    > MFP mfp2 = &B::f;
    >
    > then everything still works (presumably because f is not defined in B
    > and must then be from A). However, if I try this:
    >
    > MFP mfp3 = &B::g;
    >
    > then it complains that B::g is not of the right type since it is not a
    > member function of class A.


    Correct.

    > The protype signature is the same,


    Same as what? You seem to think that a 'B' object has
    more than one function named 'g'. There is only one,
    the member of 'A' (which is a member of 'B') .

    >both
    > (int, float), is there no way to make this work? It seemed to me that
    > it should have worked since any instance of B is still by definition an
    > instance of A.


    But 'g' is still only a member of 'A', it's not a member of 'B'.
    When you derive 'B' from 'A', 'A' is *contained* by 'B'. There
    is no 'duplication' of members. A 'B' object will have two
    'parts': the 'A' part, and the 'part' containing any members
    defined only in 'B' (if any).

    What are you trying to do that you think you can't using
    &A::g ??

    > Anyone done anything like this?


    No, because there's no need. What specifically are you
    trying to do?

    -Mike
    Mike Wahler, Jan 29, 2005
    #3
  4. Look at this way with different names:
    1) a Person has a name
    2) a Student has a name
    3) but not every Person has a grade.

    class Person
    {
    public:
    void name(int,float);
    };


    class Student : public Person
    {
    public:
    void grade(int, float);
    };

    int main() {

    typedef void (Person::*MFP)(int a, float b);

    MFP mfp1 = &Person::name;
    MFP mfp2 = &Student::name;
    MFP mfp3 = &Student::grade;
    return 0;
    }
    Matthew Schaefer, Jan 29, 2005
    #4
  5. Shezan Baig Guest

    wrote:
    > The subject basically says what I am having trouble with. For an
    > example lets say I have a class A which has a function f. I then

    also
    > have a class B which inherits from A and has a function g.
    >
    > class A
    > {
    > public: void f(int,float);
    > };
    >
    > class B : public A
    > {
    > public: void g(int, float);
    > };
    >
    >
    > Okay, now with all that setup, if I created a pointer to a member
    > function something like this:
    >
    > typedef void (A::*MFP)(int a, float b);



    This means you can call an MFP function with an object of type A.


    > if I then use it such as
    >
    > MFP mfp = &A::f;
    >
    > then everything works fine.
    >
    > even if I do:
    >
    > MFP mfp2 = &B::f;
    >
    > then everything still works (presumably because f is not defined in B


    Yes, because you can call f(...) using an object of type A. A and B
    are of type A.


    > and must then be from A). However, if I try this:
    >
    > MFP mfp3 = &B::g;
    >
    > then it complains that B::g is not of the right type since it is not

    a
    > member function of class A.


    This will not work, because you cannot call g(...) using all objects of
    type A. A pointer to 'A' is not necessarily an object of type B, so if
    I have class C, which also derives from A, I must not be able to call
    g(...) using an object of type C.

    -shez-
    Shezan Baig, Jan 29, 2005
    #5
  6. Guest

    Basically, I have a base class, I want to be able to be able to have
    keep a list of pointers to member functions such that they all have the
    same type. For instance somefunction(int, float). But I also want
    someone else to be able to subclass the baseclass, create their own
    member function with the same type, for instance someotherfunction(int,
    float) and have the function pointer still be able to point to it.
    -akiriwas
    , Jan 30, 2005
    #6
  7. Guest

    This is exactly what I'm trying to do in the case you have with MFP
    mfp3 = &Student::grade. However, when I compile the exact code you
    show with g++ it gives me the error

    error: cannot convert `void (Student::*)(int, float)' to `void
    (Person::*)(int, float)' in initialization
    Did the code you wrote work for you?

    -akiriwas
    , Jan 30, 2005
    #7
  8. Shezan Baig Guest

    wrote:
    > Basically, I have a base class, I want to be able to be able to have
    > keep a list of pointers to member functions such that they all have

    the
    > same type. For instance somefunction(int, float). But I also want
    > someone else to be able to subclass the baseclass, create their own
    > member function with the same type, for instance

    someotherfunction(int,
    > float) and have the function pointer still be able to point to it.
    > -akiriwas


    This is simply not possible.

    class A { ... };
    class B : public A { ... };
    class C : public A { ... };

    A a;
    B b;
    C c;

    If I have a function pointer to a method in class A, I am guaranteed to
    be able to call that function using any object derived from A (that
    means I can use it with 'a', 'b', and 'c').

    It *cannot* point to a method in class B. What would happen if I call
    the function using 'c'??

    Pls let us know why you are trying to do this. There is probably a
    much better, more elegant, solution instead of using function pointers.
    -shez-
    Shezan Baig, Jan 30, 2005
    #8
  9. Shezan Baig Guest

    Shezan Baig wrote:
    >
    > class A { ... };
    > class B : public A { ... };
    > class C : public A { ... };
    >
    > A a;
    > B b;
    > C c;
    >
    > If I have a function pointer to a method in class A, I am guaranteed

    to
    > be able to call that function using any object derived from A (that
    > means I can use it with 'a', 'b', and 'c').
    >
    > It *cannot* point to a method in class B. What would happen if I

    call
    > the function using 'c'??



    Or even 'a'??


    >
    > Pls let us know why you are trying to do this. There is probably a
    > much better, more elegant, solution instead of using function

    pointers.
    > -shez-
    Shezan Baig, Jan 30, 2005
    #9
  10. No, it does not work. I was trying to demonstrate intuitively that it's
    incorrect.
    Matthew Schaefer, Jan 30, 2005
    #10
  11. Guest

    Okay.. I get it now. Well, you definitely hit the nail on the head for
    what I was trying to do, but obviously now cannot. Are there any
    suggestions on what I can do to do something like it? By the way,
    thanks for the help so far.

    -akiriwas
    , Jan 30, 2005
    #11
  12. Shezan Baig Guest

    wrote:
    > Okay.. I get it now. Well, you definitely hit the nail on the head

    for
    > what I was trying to do, but obviously now cannot. Are there any
    > suggestions on what I can do to do something like it? By the way,
    > thanks for the help so far.
    >
    > -akiriwas


    You probably want to use virtual functions. For example:

    class A {
    public:
    virtual void mfp(int a, double b)
    {
    doSomething(...);
    }
    };

    class B : public A {
    public:
    virtual void mfp(int a, double b) // overriding A::mfp(...)
    {
    doSomethingElse(...);
    }
    };

    A a;
    B b;

    A *pA1 = &a;
    A *pA2 = &b;

    pA1->mfp(...); // will call A::mfp(...)
    pA2->mfp(...); // will call B::mfp(...)

    Hope this helps,
    -shez-
    Shezan Baig, Jan 30, 2005
    #12
  13. fluden Guest

    Re: Pointer-to-member-function pointing to a member function of an i

    All the other fellows said I agree, but you
    can also do exactly what you want by doing:

    MFP mfp3 = (MFP) &B::g;

    Took me forever to get this right, but it is
    a very useful technique. I have a simple
    base class A with nothing. Then I have lots of
    different methods that do various different things on many different
    classes B, C that are derived
    from A. If I add stuff to class B and allow the
    proper pointers to be set, I don't want to
    go back to A and add one more virtual class.
    Besides C also inherited from A might have
    a whole different set of functions.

    The only thing you have to be cautious
    about is to make sure when you're invoking a
    particular function, as with any typecast,
    is that the particular object supports that
    particular function. I usually keep both the
    pointer to the object and the pointer to the
    function together to make sure that this is done
    right. You can also dynamic cast to make sure
    you're point to a B object before you do the
    ->* function call

    -Fluden
    (from Porto Alegre, Brazil)
    fluden, Feb 11, 2005
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. uli
    Replies:
    3
    Views:
    521
  2. Fraser Ross
    Replies:
    4
    Views:
    1,041
    Fraser Ross
    Aug 14, 2004
  3. Praetorian
    Replies:
    11
    Views:
    2,347
    James Kanze
    Apr 3, 2008
  4. 7stud --
    Replies:
    11
    Views:
    399
    7stud --
    Nov 9, 2007
  5. somenath
    Replies:
    2
    Views:
    155
    somenath
    Aug 29, 2013
Loading...

Share This Page