Passing a pointer to member function as a parameter to another member function

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Newsgroup - Ann

    Passing a pointer to member function as a parameter to another member function

    Gurus,

    I have the following implementation of a member function:

    class A
    {
    // ...
    virtual double func(double v);
    void caller(int i, int j, double (* callee)(double) );
    void foo() {caller(1, 2, func);
    }

    The compiler told me there's a syntax error, because the pointer to a member
    function is different from a pointer to a regular function.
    That is, the func cannot be passed to caller. I checked the FAQ and in "[30]
    Pointers to member functions", it says the pointers to a member function and
    to a regular member function are different. Ok, then I tried to change it to
    static, and it works because static member function is like a regular
    function. But a static function cannot be virtual. So I have to use
    something suggested in the FAQ[30] like this:

    void caller(int i, int j, double (A::*callee)(do uble))
    {
    // ...
    (this->*callee)(param );
    }

    Isn't this an awkard solution? My question is: why was the C++ designed like
    this, couldn't there be a easy and convenient way to pass the pointer like
    a regular function? All the functions are in the same class, shouldn't the
    so-called encapsulation make it convenient? Or maybe it's due to my
    misunderstandin g and poor design?

    Thanks.


  • Jonathan Mcdougall

    #2
    Re: Passing a pointer to member function as a parameter to another member function

    On Sun, 27 Jul 2003 20:56:36 -0400, "Newsgroup - Ann"
    <news_ann@yahoo .com> wrote:
    [color=blue]
    >Gurus,
    >
    >I have the following implementation of a member function:
    >
    >class A
    >{
    >// ...
    >virtual double func(double v);
    >void caller(int i, int j, double (* callee)(double) );
    >void foo() {caller(1, 2, func);
    >}
    >
    >The compiler told me there's a syntax error, because the pointer to a member
    >function is different from a pointer to a regular function.[/color]

    Yes, this is because pointers to member function must be accompanied
    by the object to which it refers.
    [color=blue]
    >That is, the func cannot be passed to caller. I checked the FAQ and in "[30]
    >Pointers to member functions", it says the pointers to a member function and
    >to a regular member function are different. Ok, then I tried to change it to
    >static, and it works because static member function is like a regular
    >function. But a static function cannot be virtual. So I have to use
    >something suggested in the FAQ[30] like this:
    >
    >void caller(int i, int j, double (A::*callee)(do uble))
    >{
    >// ...
    > (this->*callee)(param );
    >}
    >
    >Isn't this an awkard solution?[/color]

    The solution, no. The syntax, yes :)
    [color=blue]
    >My question is: why was the C++ designed like
    >this, couldn't there be a easy and convenient way to pass the pointer like
    >a regular function?[/color]

    This is a very convinent way when you know how to use it. Typedef is
    your friend :

    typedef void (MyClass::* MyFunction)(int i1, int i2);

    Now 'MyFunction' is a pointer to a member function of MyClass which
    returns void and takes to ints.

    For your example :

    typedef double (A:: *callee)(double );

    void caller(int i, int j, callee c)
    {
    (this->c)( .. );
    }

    which is quite simpler.
    [color=blue]
    >All the functions are in the same class, shouldn't the
    >so-called encapsulation make it convenient?[/color]

    This is irrelevant. How do you want the compiler to know to which
    object this function reffers ? Would you like the compiler to default
    to 'this' if no object was provided ? This would have no sense.

    What's more, encapsulation has nothing to do with that. I see you
    have some troubles understanding this concept since you seem a bit
    harsh on that. Encapsulation hides information, that's it.


    Jonathan

    Comment

    • John Carson

      #3
      Re: Passing a pointer to member function as a parameter to another member function

      "Newsgroup - Ann" <news_ann@yahoo .com> wrote in message
      news:3f247493_1 @rcfnews.cs.uma ss.edu[color=blue]
      > Gurus,
      >
      > I have the following implementation of a member function:
      >
      > class A
      > {
      > // ...
      > virtual double func(double v);
      > void caller(int i, int j, double (* callee)(double) );
      > void foo() {caller(1, 2, func);
      > }
      >
      > The compiler told me there's a syntax error, because the pointer to a
      > member function is different from a pointer to a regular function.
      > That is, the func cannot be passed to caller. I checked the FAQ and
      > in "[30] Pointers to member functions", it says the pointers to a
      > member function and to a regular member function are different. Ok,
      > then I tried to change it to static, and it works because static
      > member function is like a regular function. But a static function
      > cannot be virtual. So I have to use something suggested in the
      > FAQ[30] like this:
      >
      > void caller(int i, int j, double (A::*callee)(do uble))
      > {
      > // ...
      > (this->*callee)(param );
      > }
      >
      > Isn't this an awkard solution? My question is: why was the C++
      > designed like this, couldn't there be a easy and convenient way to
      > pass the pointer like a regular function? All the functions are in
      > the same class, shouldn't the so-called encapsulation make it
      > convenient? Or maybe it's due to my misunderstandin g and poor design?
      >
      > Thanks.[/color]

      Pointers to member functions are very flexible. They can be used by
      other classes and at global (or namespace) scope (provided that they
      are bound to an appropriate object in either case). Moreover, even
      within the same class, a pointer to member function does not have to
      use the member data of the current object. It can use the member data
      of another object of the same class by using the other object's
      "this" pointer.

      To see why you have to use this->*callee rather than just callee,
      suppose you have two objects, a1 and a2. Then each object might store
      a pointer to the other A object, called otherAObjectPtr . In that
      case, you would be allowed to call

      otherAObjectPtr->*callee

      so that the function would use the "this" pointer (and hence the
      member data) from the other object rather than its own. It is because
      of that flexibility that you need to be explicit that you want to use
      the "this" pointer of the current object.


      --
      John Carson
      1. To reply to email address, remove donald
      2. Don't reply to email address (post here instead)

      Comment

      • Newsgroup - Ann

        #4
        Re: Passing a pointer to member function as a parameter to another member function


        "Jonathan Mcdougall" <DELjonathanmcd ougall@yahoo.ca > wrote in message
        news:vs49ivoq87 cjh9qnbei7hs9dd s1vcdhojl@4ax.c om...[color=blue]
        > On Sun, 27 Jul 2003 20:56:36 -0400, "Newsgroup - Ann"
        > <news_ann@yahoo .com> wrote:
        >[color=green]
        > >Gurus,
        > >
        > >I have the following implementation of a member function:
        > >
        > >class A
        > >{
        > >// ...
        > >virtual double func(double v);
        > >void caller(int i, int j, double (* callee)(double) );
        > >void foo() {caller(1, 2, func);
        > >}
        > >
        > >The compiler told me there's a syntax error, because the pointer to a[/color][/color]
        member[color=blue][color=green]
        > >function is different from a pointer to a regular function.[/color]
        >
        > Yes, this is because pointers to member function must be accompanied
        > by the object to which it refers.
        >[color=green]
        > >That is, the func cannot be passed to caller. I checked the FAQ and in[/color][/color]
        "[30][color=blue][color=green]
        > >Pointers to member functions", it says the pointers to a member function[/color][/color]
        and[color=blue][color=green]
        > >to a regular member function are different. Ok, then I tried to change it[/color][/color]
        to[color=blue][color=green]
        > >static, and it works because static member function is like a regular
        > >function. But a static function cannot be virtual. So I have to use
        > >something suggested in the FAQ[30] like this:
        > >
        > >void caller(int i, int j, double (A::*callee)(do uble))
        > >{
        > >// ...
        > > (this->*callee)(param );
        > >}
        > >
        > >Isn't this an awkard solution?[/color]
        >
        > The solution, no. The syntax, yes :)
        >[color=green]
        > >My question is: why was the C++ designed like
        > >this, couldn't there be a easy and convenient way to pass the pointer[/color][/color]
        like[color=blue][color=green]
        > >a regular function?[/color]
        >
        > This is a very convinent way when you know how to use it. Typedef is
        > your friend :
        >
        > typedef void (MyClass::* MyFunction)(int i1, int i2);
        >
        > Now 'MyFunction' is a pointer to a member function of MyClass which
        > returns void and takes to ints.
        >
        > For your example :
        >
        > typedef double (A:: *callee)(double );
        >
        > void caller(int i, int j, callee c)
        > {
        > (this->c)( .. );
        > }
        >
        > which is quite simpler.[/color]

        yeah, I saw this kind of solution from the FAQ I mentioned at the beginning,
        but I am more concerning about the
        (this->*callee)(param ) part. btw, shouldn't (this->c) be (this->*c)?
        [color=blue]
        >[color=green]
        > >All the functions are in the same class, shouldn't the
        > >so-called encapsulation make it convenient?[/color]
        >
        > This is irrelevant. How do you want the compiler to know to which
        > object this function reffers ? Would you like the compiler to default
        > to 'this' if no object was provided ? This would have no sense.[/color]

        Yes, the default 'this' was what I meant. Why not making any sense? The
        member data are used in this way, why not the function?
        [color=blue]
        > What's more, encapsulation has nothing to do with that. I see you
        > have some troubles understanding this concept since you seem a bit
        > harsh on that. Encapsulation hides information, that's it.[/color]
        LOL
        [color=blue]
        >
        >
        > Jonathan
        >[/color]


        Comment

        • Newsgroup - Ann

          #5
          Re: Passing a pointer to member function as a parameter to another member function

          > To see why you have to use this->*callee rather than just callee,[color=blue]
          > suppose you have two objects, a1 and a2. Then each object might store
          > a pointer to the other A object, called otherAObjectPtr . In that
          > case, you would be allowed to call
          >
          > otherAObjectPtr->*callee
          >
          > so that the function would use the "this" pointer (and hence the
          > member data) from the other object rather than its own. It is because
          > of that flexibility that you need to be explicit that you want to use
          > the "this" pointer of the current object.
          >[/color]

          but the 'this' for the reference to its own _member data_ could be omitted,
          why not the same for the _member function_?
          [color=blue]
          >
          > --
          > John Carson
          > 1. To reply to email address, remove donald
          > 2. Don't reply to email address (post here instead)[/color]


          Comment

          • John Carson

            #6
            Re: Passing a pointer to member function as a parameter to another member function

            "Newsgroup - Ann" <news_ann@yahoo .com> wrote in message
            news:3f26ecea$1 _1@rcfnews.cs.u mass.edu[color=blue][color=green]
            > > To see why you have to use this->*callee rather than just callee,
            > > suppose you have two objects, a1 and a2. Then each object might
            > > store
            > > a pointer to the other A object, called otherAObjectPtr . In that
            > > case, you would be allowed to call
            > >
            > > otherAObjectPtr->*callee
            > >
            > > so that the function would use the "this" pointer (and hence the
            > > member data) from the other object rather than its own. It is
            > > because
            > > of that flexibility that you need to be explicit that you want to
            > > use
            > > the "this" pointer of the current object.
            > >[/color]
            >
            > but the 'this' for the reference to its own _member data_ could be
            > omitted, why not the same for the _member function_?[/color]


            [Re-post after the first seemed to disappear]

            Pointers to member functions have a rather complicated character. For
            comparison, think about the following members:

            1. Ordinary data members, e.g., an int called m.
            2. Member functions, e.g., a function called foo

            When you use m within a class, it is implicitly replaced by this->m. The
            role of "this" is to identify the object to which m belongs.

            When you use foo within a class, it it implicitly replaced by this->foo. The
            role of "this" is *not* to identify the object to which foo belongs, because
            foo is the same for all objects in the class and does not belong to
            individual objects. Rather, "this" identifies the object that foo is to use
            if it needs to access member data.

            Now consider a pointer to a member function that is itself a data member of
            the A class. Suppose that there are two objects, a1 and a2, and each stores
            a pointer to a member function, called ptr. Suppose that the ptr value
            stored by a1 points to A::foo(), whereas the ptr value stored by a2 points
            to A::goo().

            Now if an A object invokes ptr, there are two bindings to be made, not one.
            These correspond to the two sorts of bindings discussed above for m and foo.

            First, it must be decided which ptr value to use --- the ptr value stored in
            a1, pointing to the function A::foo(), or the ptr value stored by a2,
            pointing to the function A::goo(). Second, in either case, it must be
            decided which member variables the member function should use, those from a1
            or those from a2, e.g., should it use the m integer from a1 or the m integer
            from a2. It is possible to mix and match, e.g., you could use the ptr value
            stored in a2 (giving the function A::goo() ), yet have the member function
            pointed to use the member data of a1.

            If, within the scope of the A class, you type:

            (this->*ptr)();

            then you are indeed being forced to make one "this" explicit. But there is a
            second "this" that is being supplied implicitly, just like it normally is.
            What you type is implicitly converted to:

            (this->*this->ptr)();

            The explicit "this" on the left shows that you want the function to use the
            member variables of the current object. The implicitly supplied "this" on
            the right shows that you want to use the ptr value of the current object.
            The general syntax is

            (pObjectSupplyi ngMemberVariabl es->*pObjectToWhic hPointerBelongs->ptr)();

            The rules concerning when "this" must be explicit and when "this" is
            supplied implicitly mean that the ptr variable is being treated like the m
            int variable but not like the foo() function --- which makes sense because
            ptr is a variable like m, not a function like foo.

            Now, you might prefer that both "this" pointers were supplied implicitly. I
            don't know what, if any, technical difficulties that might pose for compiler
            writers. But I hope that I have persuaded you that there is an underlying
            consistency in the current syntax.


            --
            John Carson
            1. To reply to email address, remove donald
            2. Don't reply to email address (post here instead)

            Comment

            Working...