Thread: custom loose coupling from string

  1. #1
    Registered User
    Join Date
    Jun 2007
    Posts
    219

    custom loose coupling from string

    assume I've a string
    Code:
    string methodName="xyz";
    Now I want someObject.methodName() or someObject->methodName() which will actually do someObject->xyz();

    Now How this job can be performed with C++.
    remember the Objectname is known however the methodName is not (e.g. methodName is specified by a string variable)

    EDIT

    I am not stuck on someObject.methodName() syntax. this can be performed by any syntax. I ultimately call the xyz() method e.g. the method with the same name as the value ofthe string methodName() somehow.

    EDIT

    Platform Independent Solutions (If possible) are most Welcome
    Last edited by noobcpp; 09-27-2008 at 05:54 AM.

  2. #2
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    One way would be to make a map of function pointers and call a method which searches the max for "xyx"... Not pretty. Or else in the calling function use an if-else if-else ladder. You can't map a string to a method name like you're trying to do. There's going to have to be an interpreter function which will translate the string to a method call.

    Edit: Something like:
    Code:
    class thing {
    private:
      typedef void (thing::*_fptr)();
      std::map<std::string, _fptr> mfp;
    
    public:
      thing() {
        mfp["one"] = &thing::one;
        mfp["two"] = &thing::two;
        mfp["three"] = &thing::three;
      }
      void one(){std::cout<<"one\n";}
      void two(){std::cout<<"two\n";}
      void three(){std::cout<<"three\n";}
    
      void call(std::string func){
        (this->*(this->mfp[func]))();
      }
    };
    
    int main( void ) {
      thing t;
      t.call("one");
      t.call("two");
      t.call("three");
    }
    Note, this solution has absolutely no error checking.
    Last edited by twomers; 09-27-2008 at 06:11 AM.

  3. #3
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    I've some idea thats like the following.
    in Constroctor callback (function Pointers) for every method will be given through some macro which will be stored in some internal map.
    Like
    CONTROL("methodName", methodName)

    nd on runtime the methodName will be resolved!!

    Is there any leackage in this plan ??

    However Is it possible to do Assembly level name resoulution at runtime and call ??
    Last edited by noobcpp; 09-27-2008 at 06:10 AM.

  4. #4
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    Check the edit of my last post. Add parameters as appropriate.

  5. #5
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    Instead of doing &thing::one; can we use this::one;

  6. #6
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    Does it work? I'd imagine not, and I'd imagine no. Though I am by no means omniscient.

  7. #7
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    I am giving your example a try.

  8. #8
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    ya your code worked. but two questions??

    1. Here you are writting the class name &thing. is there anyway to do the same thing without writting the Class name (thats why I was trying to use this instead)
    If I use &this->one instead of &thing::one compiler fires errors saying.
    Code:
    ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&thing::one'
    2. Can the same be handled if case of polymorphic types ?? e.g.
    thing extends from matter Class
    so can I use &matter::methodOfThing instead of &thing::methodOfThing.
    e.g. method will be bound at runtime ??

  9. #9
    The larch
    Join Date
    May 2006
    Posts
    3,573
    1) I believe its because member functions belong to classes, not instances. (All instances share the same function, and pass the hidden this argument to identify themselves.)

    2) They should support virtual functions. But if the map is defined to contain pointers-to-methods-of-base, then I don't think you can put pointers-to-methods-of-derived in it.

    Code:
    #include <iostream>
    #include <map>
    
    class thing {
    private:
      typedef void (thing::*_fptr)();
      std::map<std::string, _fptr> mfp;
    
    public:
      thing() {
        mfp["one"] = &thing::one;
        mfp["two"] = &thing::two;
        mfp["three"] = &thing::three;
      }
      virtual ~thing() {}
      virtual void one(){std::cout<<"one\n";}
      virtual void two(){std::cout<<"two\n";}
      virtual void three(){std::cout<<"three\n";}
    
      void call(std::string func){
        (this->*(this->mfp[func]))();
      }
    };
    
    class thingy: public thing
    {
    public:
      virtual void one(){std::cout<<"thingy_one\n";}
      virtual void two(){std::cout<<"thingy_two\n";}
      virtual void three(){std::cout<<"thingy_three\n";}
    };
    
    int main( void ) {
      thingy t;
      t.call("one");
      t.call("two");
      t.call("three");
      thing u;
      u.call("one");
      u.call("two");
      u.call("three");
    }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  10. #10
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    1) Might be able to do so with static-ally declared functions. But I'm unsure of this.
    2) A per anon's solution.

    Function pointers are fun, eh?

  11. #11
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    So still now the conclution is you must write the class name e.g. &className::methodName

    although it doesn't seem much problem in this case as I can use the parent class's name here.

    Thanks a lot for your help.

  12. #12
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    Sorry to Say But this solution doesn't work properly in case of polymorphic Classes.
    Here is my example.
    Here I've pasted my source code http://gist.github.com/13478.

    as you saw I've added a member function .
    Code:
    void addCallback(const std::string& k, _fptr fn){
      mfp[k] = fn;
    }
    Which is not accepting polymorphic types

  13. #13
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Polymorphism means that derived classes override existing methods (do the same things, but differently) and not that they add completely new methods. Also to make classes polymorphic, the methods must be virtual.

    You can't add matter::four, because that would mean that somehow you should be able to do thing.call("four"), even though thing doesn't have this method.

    Perhaps each derived class could keep its own map, and when a call is made, the derived class searches in both maps?

    You might also explain the bigger picture what you are trying to do all this.
    Last edited by anon; 09-28-2008 at 11:22 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  14. #14
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    What you're trying to do there is make a parent know about a child class. The function pointers are called via thing. Thing's methods can be called via matter. But matter's functions can't be called via thing, without some casting... I really don't know how good an idea this is, but it does the job (I highlighted the key area in red):
    Code:
    // thing.h
    class thing;
    typedef void (thing::*_thing_fptr)();
    
    class thing {
    protected:
      std::map<std::string, _thing_fptr> mfp;
    
    public:
      thing();
      virtual void one();
      virtual void two();
      virtual void three();
      virtual void add( const std::string &f_alias, _thing_fptr fptr );
    
      virtual void call( const std::string &func);
    };
    
    // thing.cpp
    thing::thing(){
      mfp["one"] = &thing::one;
      mfp["two"] = &thing::two;
      mfp["three"] = &thing::three;
    }
    void thing::one(){
      std::cout<<"One called (thing)\n";
    }
    void thing::two(){
      std::cout<<"Two called (thing)\n";
    }
    void thing::three(){
      std::cout<<"Three called (thing)\n";
    }
    void thing::add( const std::string &f_alias, _thing_fptr fp ) {
      mfp[f_alias] = fp;
    }
    
    void thing::call( const std::string &func ) {
      (this->*(this->mfp[func]))();
    }
    
    
    
    
    
    // matter.h
    class matter;
    typedef void (matter::*_matter_fptr)();
    
    class matter : public thing {
    private:
    
    public:
      matter(){}
      virtual void one();
      virtual void four();
      virtual void add( const std::string &f_alias, _matter_fptr fp );
      ~matter(){}
    };
    
    // matter.cpp
    void matter::four() {
      std::cout<<"Four called (matter)\n";
    }
    void matter::one() {
      std::cout<< "Four called (matter)\n";
    }
    void matter::add( const std::string &f_alias, _matter_fptr fp ) {
      mfp[f_alias] = reinterpret_cast<_thing_fptr>( fp );
    }
    
    
    // main
    int main( void ) {
      // Add basic
      thing t;
      t.call("one");
      t.call("two");
      t.call("three");
    
      // Add alias
      t.add( "my_one", thing::one );
      t.call( "my_one" );
    
      // child
      matter m;
      m.add( "fourth_one", matter::four );
      m.call( "fourth_one" );
    
      return 0;
    }
    Edit: Actually. For those who are more in the know than I is that code dangerous? It works, but it's clearly weird and freaky - a child function is being casted to its parent function pointer typedef and child function doesn't exist in its parent.
    Last edited by twomers; 09-28-2008 at 11:56 AM.

  15. #15
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    Thanks for your example.
    I forgot about reinterpret_cast.
    I can use
    Code:
    m.addCallback("four", reinterpret_cast<void (thing::*)()>(&matter::four));
    from the child Class with no further change to it.

    But one thing I'd like to know with Signal Slot mechanism qt binds methods to objects at runtime.
    and I've also seen that Qt prints an error message at runtime if it cannot bind the method with the specified object (e.g. method not found)
    How does this work ??
    Last edited by noobcpp; 09-28-2008 at 12:03 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Please check my C++
    By csonx_p in forum C++ Programming
    Replies: 263
    Last Post: 07-24-2008, 09:20 AM
  2. Inheritance Hierarchy for a Package class
    By twickre in forum C++ Programming
    Replies: 7
    Last Post: 12-08-2007, 04:13 PM
  3. Custom String Parsing Function
    By Unregistered in forum C++ Programming
    Replies: 2
    Last Post: 05-01-2002, 11:07 PM
  4. string handling
    By lessrain in forum C Programming
    Replies: 3
    Last Post: 04-24-2002, 07:36 PM