Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. [SOLVED] Passing member functions of one class to the constructor of another class using pointers.
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] Passing member functions of one class to the constructor of another class using pointers.

Scheduled Pinned Locked Moved C++ Gurus
11 Posts 3 Posters 9.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    valandil211
    wrote on last edited by
    #1

    Hi!

    I am trying to understand function pointers, but having a hard time with it.

    I want to create a class (ControlChaos) that takes a MultiMaps object. Now the hard part: I also want a ControlChaos (and any derived classes) instance to have access to some specific MultiMaps ( or of any of its daugther classes) member functions. I want to be able to specify those functions in the constructor of ControlChaos (or with accessor functions).

    Are there multiple ways to do this? I only thought of function pointers, but even then the syntax is not making sense to me.

    Could someone provide: (a) another solution? or (b) a simple example with function pointers?

    Here's what I have done so far (doesn't compile):

    @class ControlChaos
    {
    public:
    /*! Base constructor will be the base
    * of all control routines.
    */
    ControlChaos(MultiMaps& _map,
    mat orbitPoints,
    colvec initCond,
    double (MultiMaps::*getPara)(),
    void (MultiMaps::*setPara)(double),
    double deltaMax,
    double epsilonNeighborhood,
    int controlIterations,
    int maxIterations);
    protected:
    double (MultiMaps::*getParameter)() = NULL;
    void (MultiMaps::*setParameter)(double) = NULL;

    /* Other stuff. */
    };
    @

    And the definition:
    @
    ControlChaos::ControlChaos(MultiMaps &_map,
    mat orbitPoints,
    colvec initCond,
    double (MultiMaps::*getPara)(),
    void (MultiMaps::setPara)(double),
    double deltaMax,
    double epsilonNeighborhood,
    int controlIterations,
    int maxIterations)
    : map(_map), getParameter(getPara), setParameter(setPara)
    {
    /
    Definition (not relevant here). */
    }

    /* Function that does not compile. */
    mat ControlChaos::control()
    {
    setDefaultParameter((this->*getParameter()));
    }
    @

    where setDefaultParameter(double) is a member function that returns void. Compile sez:
    @
    dyn_controlChaos.cpp:35: error: must use '.' or '->' to call pointer-to-member function in '((ControlChaos*)this)->ControlChaos::getParameter (...)', e.g. '(... ->* ((ControlChaos*)this)->ControlChaos::getParameter) (...)'
    @

    I've tried with different dereferencing schemes, but it still doesn't work. I'm not sure what should be referenced or not.

    Complete code is available "here":http://code.google.com/p/libdynamica/source/browse/#svn/trunk and the relevant files are dyn_multiFunctor_multiMaps.* and dyn_controlChaos.*.

    Thanks everyone!

    Joey Dumont

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mkuettler
      wrote on last edited by
      #2

      Hi,

      I'm not sure about the dereferencing syntax (I would have to ask google or try that out), but I am confused about the way you want to call the function. Did you maybe want to write map->*getParameter() instead of this->*getParameter() ? Since getParameter is a pointer to a member function of MultiMaps you should call it on an object of that type.
      The compiler message does not appear to be very helpful here. It would be interesting if clang gives a more useful error.

      1 Reply Last reply
      0
      • V Offline
        V Offline
        valandil211
        wrote on last edited by
        #3

        Yes, I thought the same thing, but the compiler gives the same error. The problem is the following. I'm trying to dereference a pointer that points to a member function in class MultiMaps. However, that pointer is itself a member variable of class ControlChaos. Just thinking about the syntax of dereferencing that makes me want to cry. A member function pointer is a member variable of another class which has no link whatsoever with the class which contains the member function I want to access.

        This "article":http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible?display=Print has some interesting stuff on member function pointers, but not what I have in mind. Is there a way to do this via templating?

        I could also make the member variables of MultiMaps and its derived classes public and simply pass their address in ControlChaos and modify them directly from the ControlChaos class, but that just seems bad programming.

        Joey Dumont

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mkuettler
          wrote on last edited by
          #4

          Still, you want to call the function on the map object, so it has to appear somewhere in this line. I would try something like
          @
          map.*getParameter
          @

          or
          @
          map.*(this->getParameter)
          @

          1 Reply Last reply
          0
          • A Offline
            A Offline
            andre
            wrote on last edited by
            #5

            Did you read and understand the "FAQ":http://www.parashift.com/c++-faq-lite/pointers-to-members.html on the topic on pointers-to-member-functions?

            1 Reply Last reply
            0
            • V Offline
              V Offline
              valandil211
              wrote on last edited by
              #6

              Thanks Andre for the link. I've read the article and (partially) understood it. I'll be using typedef from now on. After some reflection, it seems that I'm doing something wrong. I don't see how functionoids would help me in this case.

              If, in the constructor of ControlChaos, I passed in the addresses of the functions I want to access and store them in a pointer-to-member-function that is a member variable of the class ControlChaos, would it work?

              Or, again, do you see any other way to do this? I reiterate, I want to be able to access public member functions of class MultiMaps (or rather member functions of its derived classes) from another class, ControlChaos. ControlChaos has-a MultiMaps object within it. However, the exact function to be called will vary from instance to instance.

              Thanks everyone for your time, and putting up with me.

              Joey Dumont

              1 Reply Last reply
              0
              • A Offline
                A Offline
                andre
                wrote on last edited by
                #7

                Yes, the setup as such can certainly work. I use it in my current project at work as well.

                Here is a small snippet:
                @
                typedef void (ImageMetadata::IntSetterFn)(int value);
                typedef int (ImageMetadata::IntGetterFn)()const;
                class IntXmlPropertyMapper: public AbstractXmlPropertyMapper {
                public:
                IntXmlPropertyMapper(IntGetterFn getterFn, IntSetterFn setterFn,
                QString nameSpace, QString property, Level level = Default);
                virtual bool fromStream(ImageMetadata
                object, QXmlStreamReader
                reader) const;
                virtual bool toStream (const ImageMetadata* object, QXmlStreamWriter* writer) const;

                private:
                IntSetterFn m_setterFunction; //function pointer to setter function for property
                IntGetterFn m_getterFunction; //function pointer to getter function for property
                };
                @

                This class is part of a system that I use to (de-)serialize objects to/from XML, by defining a mapping. The implementation of the constructor is trivial: just a set of assignments to the relevant member variables. When called, I use this syntax:

                @
                CALL_MEMBER_FN(object,m_setterFunction)(value);
                @
                with the CALL_MEMBER_FN defined as
                @
                #define CALL_MEMBER_FN(object,ptrToMember) ((object)->*(ptrToMember))
                @
                as per in the FAQ I linked against.

                Edit:
                P.S. And no, I could not use Q_PROPERTY in this case :-)

                1 Reply Last reply
                0
                • V Offline
                  V Offline
                  valandil211
                  wrote on last edited by
                  #8

                  Thanks! I implemented it as you did, Andre, and everything works fine.

                  Apart from the weird syntax, this feature looks very useful too me. Why isn't anyone using this?

                  Anyhow, for someone reading this in the future, I'd like to reiterate that the complete code is available "here":http://code.google.com/p/libdynamica/ . Happy coding!

                  Joey Dumont

                  1 Reply Last reply
                  0
                  • V Offline
                    V Offline
                    valandil211
                    wrote on last edited by
                    #9

                    Unfortunately, I think we'll have to backtrack. The code now compiles. However, it is a library, so nothing used it.

                    I tried to do this on code that uses the library.

                    @typedef double (HenonMap::*mapsGetPtr)();
                    typedef void (HenonMap::*mapsSetPtr)(double para);
                    HenonMap *hmap = &hMap;
                    mapsGetPtr get = &HenonMap::getA;
                    mapsSetPtr set = &HenonMap::setA;

                    ControlOGY ogy = ControlOGY(hmap,fixedPoint,init,get, set,delta,epsilon,
                    controlIterations,3000,contra.row(0),
                    parametric.row(0));
                    @

                    but the compiler complains that (I left out some crap)

                    @/2-OGYControl/main.cpp:264: error: no matching function for call to 'ControlOGY::ControlOGY(HenonMap*&, arma::mat&, arma::colvec&, double (HenonMap::&)(), void (HenonMap::&)(double), double&, double&, int&, int, arma::subview_row<double>, arma::subview_row<double>)'
                    /usr/local/include/dynamica_bits/dyn_controlChaos_controlOGY.h:22: note: no known conversion for argument 4 from 'mapsGetPtr {aka double (HenonMap::)()}' to 'mapsGetPtr {aka double (MultiMaps::)()}'@

                    where HenonMap is a derived class of MultiMaps and ControlOGY is a derived class of ControlChaos. This "article":http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible seemed to imply that it was possible to use member function pointers with inheritance.

                    Since HenonMap is-a MultiMaps, I don't really see the issue.

                    Joey Dumont

                    1 Reply Last reply
                    0
                    • V Offline
                      V Offline
                      valandil211
                      wrote on last edited by
                      #10

                      Also, could "lambda functions":http://www.cprogramming.com/c++11/c++11-lambda-closures.html be used instead of function pointers?

                      Joey Dumont

                      1 Reply Last reply
                      0
                      • V Offline
                        V Offline
                        valandil211
                        wrote on last edited by
                        #11

                        Hi everyone!

                        The solution is simple: before passing your pointers-to-daughter-classes to the constructor, make a simple static cast to the base class. I've tested it with the code above and everything works fine. The solution comes
                        from "StackOverflow":http://stackoverflow.com/questions/11497100/accessing-a-member-function-from-another-class-without-prior-knowledge-of-the-sp.

                        Have a good day, and thanks!

                        Joey Dumont

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved