Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

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

    C++ Gurus
    3
    11
    8496
    Loading More Posts
    • 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
      valandil211 last edited by

      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 Reply Quote 0
      • M
        mkuettler last edited by

        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 Reply Quote 0
        • V
          valandil211 last edited by

          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 Reply Quote 0
          • M
            mkuettler last edited by

            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 Reply Quote 0
            • A
              andre last edited by

              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 Reply Quote 0
              • V
                valandil211 last edited by

                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 Reply Quote 0
                • A
                  andre last edited by

                  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 Reply Quote 0
                  • V
                    valandil211 last edited by

                    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 Reply Quote 0
                    • V
                      valandil211 last edited by

                      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 Reply Quote 0
                      • V
                        valandil211 last edited by

                        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 Reply Quote 0
                        • V
                          valandil211 last edited by

                          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 Reply Quote 0
                          • First post
                            Last post