Pointers to member functions.

Discussion in 'C++' started by Gregory L. Hansen, May 8, 2005.

  1. I'm playing with a simulation where different parts of a system, like a
    controller or a thermometer or a thermal mass, are represented as classes,
    instantiated, and connected together like Tinkertoys. My thought at first
    was that each class would have a member function like get_ouput(). When
    some object like a thermal mass needs an input, like heat from a control
    system, my thought was to add a pointer to that object to an internal
    list, like

    target.add_heat(&controller);

    But I've discovered I want a little more flexibility to choose a member
    function as the input. So I'd like to use something analogous to pointers
    to regular functions, like

    float (*pf)();
    pf = controller.get_heat;
    target.add_heat(pf);

    But I've been playing with variations on that theme and I can't get it to
    work.

    Can I do this sort of thing in C++?

    --
    "Awareness means not just a vague, comfortable, fuzzy feeling. It means
    explicit knowledge of current conditions." -- NBSR Radiation Safety
    Training
     
    Gregory L. Hansen, May 8, 2005
    #1
    1. Advertising

  2. Gregory L. Hansen wrote:
    > I'm playing with a simulation where different parts of a system, like
    > a controller or a thermometer or a thermal mass, are represented as
    > classes, instantiated, and connected together like Tinkertoys. My
    > thought at first was that each class would have a member function
    > like get_ouput(). When some object like a thermal mass needs an
    > input, like heat from a control system, my thought was to add a
    > pointer to that object to an internal list, like
    >
    > target.add_heat(&controller);
    >
    > But I've discovered I want a little more flexibility to choose a
    > member function as the input. So I'd like to use something analogous
    > to pointers to regular functions, like
    >
    > float (*pf)();
    > pf = controller.get_heat;
    > target.add_heat(pf);
    >
    > But I've been playing with variations on that theme and I can't get
    > it to work.


    What specifically can't you get to work?

    > Can I do this sort of thing in C++?


    It's a good question, but why are you asking us? The question is
    essentially about *your* ability, so, can *you* do it? If you wanted
    to ask whether it's *possible* to do in C++, then the answer is "yes".
    C++ is a general purpose language, and there is almost nothing that
    cannot be done with it.

    V
     
    Victor Bazarov, May 8, 2005
    #2
    1. Advertising

  3. Gregory L. Hansen wrote:
    > I'm playing with a simulation where different parts of a system, like a
    > controller or a thermometer or a thermal mass, are represented as classes,
    > instantiated, and connected together like Tinkertoys. My thought at first
    > was that each class would have a member function like get_ouput(). When
    > some object like a thermal mass needs an input, like heat from a control
    > system, my thought was to add a pointer to that object to an internal
    > list, like
    >
    > target.add_heat(&controller);
    >
    > But I've discovered I want a little more flexibility to choose a member
    > function as the input. So I'd like to use something analogous to pointers
    > to regular functions, like
    >
    > float (*pf)();
    > pf = controller.get_heat;
    > target.add_heat(pf);
    >
    > But I've been playing with variations on that theme and I can't get it to
    > work.
    >
    > Can I do this sort of thing in C++?
    >


    I don't think so, unless the functions are
    non-member functions.

    You might read the book "Design Patterns, Elements of
    Reusable Object-Oriented Software" by Gamma, Helm,
    Johnson, and Vlissides.

    Perhaps an MVC (Model/View/Controller) approach, or the
    "Mediator" design pattern would best meet your needs.

    To quote from the "Design Patterns" Mediator section:

    <quote>
    Define an object that encapsulates how a set of objects interact.
    Mediator promotes loose coupling by keeping objects from referring
    to each other explicitly, and it lets you vary their interaction
    independently.
    ..
    ..
    ..
    Colleagues send and receive requests from a Mediator object.
    The mediator implements the cooperative behavior by routing
    requests between the appropriate colleague(s).
    </quote>

    Regards,
    Larry

    --
    Anti-spam address, change each 'X' to '.' to reply directly.
     
    Larry I Smith, May 8, 2005
    #3
  4. Gregory L. Hansen

    Abecedarian Guest

    Gregory L. Hansen wrote:
    > But I've discovered I want a little more flexibility to choose a

    member
    > function as the input. So I'd like to use something analogous to

    pointers
    > to regular functions, like
    >
    > float (*pf)();
    > pf = controller.get_heat;
    > target.add_heat(pf);
    >
    > But I've been playing with variations on that theme and I can't get

    it to
    > work.
    > Can I do this sort of thing in C++?


    Try these links:
    http://www.parashift.com/c -faq-lite/pointers-to-members.html
    http://www.newty.de/fpt/index.html

    ::A::
     
    Abecedarian, May 8, 2005
    #4
  5. In article <>,
    Abecedarian <> wrote:
    >Gregory L. Hansen wrote:
    >> But I've discovered I want a little more flexibility to choose a

    >member
    >> function as the input. So I'd like to use something analogous to

    >pointers
    >> to regular functions, like
    >>
    >> float (*pf)();
    >> pf = controller.get_heat;
    >> target.add_heat(pf);
    >>
    >> But I've been playing with variations on that theme and I can't get

    >it to
    >> work.
    >> Can I do this sort of thing in C++?

    >
    >Try these links:
    >http://www.parashift.com/c -faq-lite/pointers-to-members.html
    >http://www.newty.de/fpt/index.html


    It confusing, I'm not sure I understand it. Looks like I need a static
    wrapper for a non-static member. And if I have multiple possible
    members in a single object, I need multiple static wrappers, and need to
    select which one to call. So I think I would be no better off than
    having a generic float output(int) member with a switch statement to
    select one of several possible outputs.

    It would be easier if I could do something like

    class Class{
    public:
    int x;
    int y;
    };

    int main()
    {
    Class a;
    int * p;
    p = &(a.x);
    cout << "I just randomly decided to get " << *p << endl;
    p = &(a.y);
    cout << "Now the other one, " << *p << endl;
    return 0;
    }

    But we're not supposed to make data members publicly accessible when we do
    C++. We're supposed to do

    class Class{
    private:
    int x;
    public:
    int get_x() {return x;}
    };

    I would be cast out as a pariah, but maybe I'll use public variables
    anyway. At least I know how, and it saves on running code like

    if (selection == kSelectX)
    return x;
    else if (selection == kSelectY)
    return y;
    else if...

    again and again in loops.

    --
    "You're not as dumb as you look. Or sound. Or our best testing
    indicates." -- Monty Burns to Homer Simpson
     
    Gregory L. Hansen, May 9, 2005
    #5
  6. "Gregory L. Hansen" wrote:
    >
    > >
    > >Try these links:
    > >http://www.parashift.com/c -faq-lite/pointers-to-members.html
    > >http://www.newty.de/fpt/index.html

    >
    > It confusing, I'm not sure I understand it.


    The main point is:
    The function pointer alone is not sufficient.
    You want to call a member function of an object. For this
    you need 2 informations: a pointer to the object itself and
    a pointer to the member function of that object.

    > Looks like I need a static
    > wrapper for a non-static member.


    That's the usual way it is done, when the interface of the class where
    you register the callback is already fixed and cannot be changed.
    But that is not your situation. You can change that interface to pass
    those 2 informations: the pointer to the object and the pointer to a member
    function of that object.

    Study the following example. It shows how to call a a function foo and pass
    an object and a member function of that object to it:

    #include <iostream>


    class Class
    {
    public:
    double twice( double Nr ) { return 2 * Nr; }
    double triple( double Nr ) { return 3 * Nr; }
    };

    typedef double (Class::*CallBackFnct)( double );

    void foo( Class* pObject, CallBackFnct Function )
    {
    std::cout << (pObject->*(Function))( 5 ) << std::endl;
    }

    int main()
    {
    Class a;

    foo( &a, Class::twice );
    foo( &a, Class::triple );
    }



    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, May 9, 2005
    #6
  7. In article <>,
    Karl Heinz Buchegger <> wrote:
    >"Gregory L. Hansen" wrote:
    >>
    >> >
    >> >Try these links:
    >> >http://www.parashift.com/c -faq-lite/pointers-to-members.html
    >> >http://www.newty.de/fpt/index.html

    >>
    >> It confusing, I'm not sure I understand it.

    >
    >The main point is:
    >The function pointer alone is not sufficient.
    >You want to call a member function of an object. For this
    >you need 2 informations: a pointer to the object itself and
    >a pointer to the member function of that object.
    >
    >> Looks like I need a static
    >> wrapper for a non-static member.

    >
    >That's the usual way it is done, when the interface of the class where
    >you register the callback is already fixed and cannot be changed.
    >But that is not your situation. You can change that interface to pass
    >those 2 informations: the pointer to the object and the pointer to a member
    >function of that object.
    >
    >Study the following example. It shows how to call a a function foo and pass
    >an object and a member function of that object to it:


    Looks like a clear example, but I need to spend some time with it to see
    if I understand it. And, well, there seems to be little point in
    discussing it before I do.

    Thanks, I appreciate it.

    >
    >#include <iostream>
    >
    >
    >class Class
    >{
    > public:
    > double twice( double Nr ) { return 2 * Nr; }
    > double triple( double Nr ) { return 3 * Nr; }
    >};
    >
    >typedef double (Class::*CallBackFnct)( double );
    >
    >void foo( Class* pObject, CallBackFnct Function )
    >{
    > std::cout << (pObject->*(Function))( 5 ) << std::endl;
    >}
    >
    >int main()
    >{
    > Class a;
    >
    > foo( &a, Class::twice );
    > foo( &a, Class::triple );
    >}
    >
    >
    >
    >--
    >Karl Heinz Buchegger
    >



    --
    "Pain is temporary, quitting lasts forever" -- Lance Armstrong
     
    Gregory L. Hansen, May 10, 2005
    #7
  8. In article <>,
    Karl Heinz Buchegger <> wrote:
    >"Gregory L. Hansen" wrote:


    >Study the following example. It shows how to call a a function foo and pass
    >an object and a member function of that object to it:


    Cool, it does work for me! I made my own function to pass things to. And
    reducing it to the most basic level looks like

    #include <iostream>

    class Class
    {
    public:
    double twice( double Nr ) { return 2 * Nr; }
    double triple( double Nr ) { return 3 * Nr; }
    };

    int main()
    {
    Class a;
    Class *c;
    c = &a;
    double (Class::* f)(double);
    f = Class::twice;
    cout << "Defined my own pointer, giving " << (a.*(f))(3) << endl;
    f = Class::triple;
    cout << "And then " << (c->*(f))(3) << endl;
    }

    And no static wrapper functions. That actually looks very much like
    the sort of thing I wanted to do, except I didn't know the syntax.

    Thanks!


    --
    "Usenet is like a herd of performing elephants with diarrhea -- massive,
    difficult to redirect, awe-inspiring, entertaining, and a source of
    mind-boggling amounts of excrement when you least expect it. "
    -- Gene Spafford, 1992
     
    Gregory L. Hansen, May 10, 2005
    #8
  9. In article <d5p5ii$emn$>,
    Gregory L. Hansen <> wrote:
    >In article <>,
    >Karl Heinz Buchegger <> wrote:
    >>"Gregory L. Hansen" wrote:

    >
    >>Study the following example. It shows how to call a a function foo and pass
    >>an object and a member function of that object to it:

    >
    >Cool, it does work for me! I made my own function to pass things to. And
    >reducing it to the most basic level looks like


    Except that my compiler keeps complaining about illegal implicit
    typecasting, giving Warnings but not compilation-stopping Errors. What's
    up with that?

    --
    "The polhode rolls without slipping on the herpolhode lying in the
    invariable plane." -- Goldstein, Classical Mechanics 2nd. ed., p207.
     
    Gregory L. Hansen, May 10, 2005
    #9
  10. "Gregory L. Hansen" wrote:
    >
    > In article <d5p5ii$emn$>,
    > Gregory L. Hansen <> wrote:
    > >In article <>,
    > >Karl Heinz Buchegger <> wrote:
    > >>"Gregory L. Hansen" wrote:

    > >
    > >>Study the following example. It shows how to call a a function foo and pass
    > >>an object and a member function of that object to it:

    > >
    > >Cool, it does work for me! I made my own function to pass things to. And
    > >reducing it to the most basic level looks like

    >
    > Except that my compiler keeps complaining about illegal implicit
    > typecasting, giving Warnings but not compilation-stopping Errors. What's
    > up with that?
    >


    Rule number one:

    if( you don't show us the actual code you have &&
    don't tell us the exact error message &&
    which line it refers to ) {
    Nobody is able to help you
    but the error is in line 42, as usual
    }
    else {
    Someone can look at your code and try to figure out
    what the problem could be
    }

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, May 10, 2005
    #10
  11. In article <>,
    Karl Heinz Buchegger <> wrote:
    >"Gregory L. Hansen" wrote:
    >>
    >> In article <d5p5ii$emn$>,
    >> Gregory L. Hansen <> wrote:
    >> >In article <>,
    >> >Karl Heinz Buchegger <> wrote:
    >> >>"Gregory L. Hansen" wrote:
    >> >
    >> >>Study the following example. It shows how to call a a function foo and pass
    >> >>an object and a member function of that object to it:
    >> >
    >> >Cool, it does work for me! I made my own function to pass things to. And
    >> >reducing it to the most basic level looks like

    >>
    >> Except that my compiler keeps complaining about illegal implicit
    >> typecasting, giving Warnings but not compilation-stopping Errors. What's
    >> up with that?
    >>

    >
    >Rule number one:
    >
    > if( you don't show us the actual code you have &&
    > don't tell us the exact error message &&
    > which line it refers to ) {
    > Nobody is able to help you
    > but the error is in line 42, as usual
    > }
    > else {
    > Someone can look at your code and try to figure out
    > what the problem could be
    > }


    In the code you gave two messages ago, in main(). Specifically

    int main()
    {
    Class a;

    foo( &a, Class::twice );
    foo( &a, Class::triple );
    }

    gcc won't compile it, and says--

    karl.cpp: In function `int main()':
    karl.cpp:22: assuming pointer to member `double Class::twice(double)'
    karl.cpp:22: (a pointer to member can only be formed with `&
    Class::twice(double)')
    karl.cpp:23: assuming pointer to member `double Class::triple(double)'

    CodeWarrior will compile and run it, but warns "illegal implicit member
    pointer conversion" on those two lines.

    --
    "When the fool walks through the street, in his lack of understanding he
    calls everything foolish." -- Ecclesiastes 10:3, New American Bible
     
    Gregory L. Hansen, May 10, 2005
    #11
  12. "Gregory L. Hansen" wrote:
    >
    > In the code you gave two messages ago, in main(). Specifically
    >
    > int main()
    > {
    > Class a;
    >
    > foo( &a, Class::twice );
    > foo( &a, Class::triple );
    > }
    >
    > gcc won't compile it, and says--
    >
    > karl.cpp: In function `int main()':
    > karl.cpp:22: assuming pointer to member `double Class::twice(double)'


    Here it says: I assume that with "Class::twice" you mean a pointer
    to the member function "double Class::twice(double)"
    Please check, that indeed this is what you ment.

    > karl.cpp:22: (a pointer to member can only be formed with `&


    And here it tells you what to do about it: use an '&' to explicitely
    form the pointer:

    foo( &a, &Class::twice );

    What's complicated about that? The compiler even tells you what to do.

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, May 11, 2005
    #12
  13. In article <>,
    Karl Heinz Buchegger <> wrote:
    >"Gregory L. Hansen" wrote:
    >>
    >> In the code you gave two messages ago, in main(). Specifically
    >>
    >> int main()
    >> {
    >> Class a;
    >>
    >> foo( &a, Class::twice );
    >> foo( &a, Class::triple );
    >> }
    >>
    >> gcc won't compile it, and says--
    >>
    >> karl.cpp: In function `int main()':
    >> karl.cpp:22: assuming pointer to member `double Class::twice(double)'

    >
    >Here it says: I assume that with "Class::twice" you mean a pointer
    > to the member function "double Class::twice(double)"
    > Please check, that indeed this is what you ment.
    >
    >> karl.cpp:22: (a pointer to member can only be formed with `&

    >
    >And here it tells you what to do about it: use an '&' to explicitely
    >form the pointer:
    >
    > foo( &a, &Class::twice );
    >
    >What's complicated about that? The compiler even tells you what to do.


    Well, I tried that with

    foo(&a, &(Class::twice));

    and was told

    karl.cpp: In function `int main()':
    karl.cpp:22: Internal compiler error in resolve_offset_ref, at
    cp/init.c:1886
    Please submit a full bug report,
    with preprocessed source if appropriate.
    See <URL:http://bugzilla.redhat.com/bugzilla/> for instructions.

    When I try it without the parentheses on my shell account I get a lot of
    error messages related to std. There must be a library not installed or a
    path not set or something. When I remove the output I get

    //#include <iostream>
    //using namespace std;

    class Class
    {
    public:
    double twice( double Nr ) { return 2 * Nr; }
    double triple( double Nr ) { return 3 * Nr; }
    };

    typedef double (Class::*CallBackFnct)( double );

    void foo( Class* pObject, CallBackFnct Function )
    {
    // cout << (pObject->*(Function))( 5 ) << endl;
    double x = (pObject->*(Function))(5);
    }

    int main()
    {
    Class a;

    foo( &a, &Class::twice );
    foo( &a, &Class::triple );
    }

    : $ gcc karl.cpp
    /tmp/cc8RybIb.o(.eh_frame+0x11): undefined reference to
    `__gxx_personality_v0'
    collect2: ld returned 1 exit status
    : $


    I don't understand the error message. At that point I figured something
    was wrong, and didn't bother trying it with CodeWarrior. But I tried it
    just now, with the ampersand and without the parentheses, and it ran just
    fine.

    --
    "No one need be surprised that the subject of contagion was not clear to
    our ancestors."-- Heironymus Fracastorius, 1546
     
    Gregory L. Hansen, May 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. Hamish
    Replies:
    3
    Views:
    607
    Alf P. Steinbach
    Jan 25, 2008
  2. Hicham Mouline
    Replies:
    0
    Views:
    456
    Hicham Mouline
    Apr 23, 2009
  3. Hicham Mouline
    Replies:
    1
    Views:
    444
    Michael DOUBEZ
    Apr 24, 2009
  4. paul
    Replies:
    8
    Views:
    745
    Alf P. Steinbach
    Apr 30, 2009
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    739
Loading...

Share This Page