Thread: Passing A Function From One Object to Another

  1. #1
    Registered User HalNineThousand's Avatar
    Join Date
    Mar 2008
    Posts
    43

    Passing A Function From One Object to Another

    I have a control class that interacts with hardware attached to the computer. That includes a large number of function calls for performing actions (like turning it on or off, specifying settings, and so on), and it also involves a large number of calls for retrieving data.

    From the start I've broken it into other files, and then, as I got used to C++ (this is my first work in C++, so I've been using this language for less than 3 weeks now), I created a class in each file and changed over to OOP. (Please, no comments on how I should have done that from the start -- I had to learn the different facets of the language as I went along.)

    I have the main class, which I'll call HWControl, then I have the class that actually sends commands to the hardware, which we can call HWCommands, then a listener that receives all the output from the hardware, processes it, and turns it into usable data, HWListener.

    As I said, both HWCommands and HWListener have a LOT of specialized functions. Putting all the function calls in one class would be unwieldy, but on the other hand, I want them all available to anyone using this class.

    I doubt what I'm asking is possible, but is there a way to pass a function call through from one object to the next without having to specify each function itself? I know I can do something like this:
    Code:
    string HWControl::getPowerState() {
    	return hwlisten.getPowerState();
    }
    but is there some way to do this by getting a list of functions in HWListen and HWCommands and if a call is made to HWControl through such a function, just pass it on to the other class? If I do it this way, whenever I change HWCommands or HWListen, I have to make the similar changes in HWControl, which can be a maintenance issue (at least in terms of my own senility).

    While I don't think this is possible, I've been quite impressed by the flexibility of C++ and figure by asking about this, that there's a good chance there's a feature I don't know about that might help me in some way here or some other way to handle it.

    I've seriously considered, instead of having, say, 40 function calls for commands, to have one function that will process a string with the command and the arguments (which is quite easy and already done for my command line testing). I could do the same for getting output from the device by having one function call that takes a string with the name of the info needed as a parameter instead of providing 20-30 calls asking for each different piece of information, but I know programmers don't seem to like that kind of interface.

    Any suggestions or comments?

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Using something akin to IOCTL calls would be one solution - IOCTL calls generally take a constant number (enum or #define) and an input and output parameter (often optional, so NULL can be used to indicate "no input" or "no output". So one IOCTL call may be GetPowerState.

    The actual IOCTL code will then call HWListen.GetPowerState(), but to add that is only a simple case-label in a switch statement.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    There's no facility for enumerating functions and automatically creating forwarders, though.

    You might get something out of the use of inheritance, but I think that would be the wrong design here. Still, needing so many forwarders also indicates a design problem.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  4. #4
    Registered User HalNineThousand's Avatar
    Join Date
    Mar 2008
    Posts
    43
    Quote Originally Posted by CornedBee View Post
    Still, needing so many forwarders also indicates a design problem.
    Yeah, I was thinking that, as well. I can either put a huge number of function calls in the main class or use forwarders or go with just a few calls and specifying the function as an argument, for example, instead of having:
    Code:
    void tune(int freq, string band) {
    	//do stuff to tune the radio to given frequency and band
    	return;
    }
    Which would be one of about 40 functions to tune the radio, set the volume, bass, treble, and so on, I was thinking of simplifying it with something like:
    Code:
    void radio_command(string command) {
    	//code here to dispatch to the proper command
    	return;
    }
    I'd also overload that so there would be versions of radio_command() that take 1, 2, or 3 arguments that could be strings or ints, depending on what is needed for that command.

    Am I dealing with issues in the kind of interface "most" programmers would tend to want to use? (I put it in quotes because I know preferences vary, but there are some preferences that tend to turn into undeclared standards.) In other words, would there be any reason to go with an API on this that has a large number of functions which each function doing one action as opposed to one like the 2nd example?

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    It sounds like you have a pretty poor design. Perhaps having ONE function to set the volume, bass and treble in one call would make more sense.

    To allow for "not remembering values", you can use a special value to say "don't change this", e.g. -1, so if you only want to set the volume, then use something like
    Code:
    SetVolumeBassTreble(channel, newVolume, -1, -1)
    Why do you need to have multiple layers, by the way? Are you handling multiple types or instances of hardware, or what?

    In my experience, it's better to make an interface that "does the right thing", than one that is all singing and dancing, with lots of variations.

    Certainly, using strings to parse things in a driver seems a bit overkill - it just makes the code slow, and driver should be optimized to be fast - and if that means some hard graft from the programmer, so be it.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User HalNineThousand's Avatar
    Join Date
    Mar 2008
    Posts
    43
    The reason it's done in multiple objects is because of file size, essentially. There's a lot of code for the part of the program that sends commands to the radio and a lot for the part that listens for data and saves it in settings. I separated them for my own sanity in keeping track of the source and separating the functions according to type and use.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Ok, fair enough. But that doesn't mean that you have to merge them back together in a common class, does it?

    Just have a "control" object, and another "listener" object. That way, you don't have to have a huge list of
    Code:
    common::function() { 
        listener::function(); 
    }
    that essentially adds no further functionality at all, other than managing the listener and control objects together, and adding a lot of extra code.

    But it's your design, so you do as you like with it, of course

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Nov 2006
    Posts
    85
    Hmm I don't use the friend Keywork much (so this might not work) but it sounds like it might be usefull. You could declare both classes friends of the other.


    Code:
    class HWCommands
    {
         public:
              friend class HWListen;
    };
    and visa versa.

    I personally would go for the total redesign of you code.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> I doubt what I'm asking is possible, but is there a way to pass a function call through from one object to the next without having to specify each function itself?

    generally, yes, but there are many ways to go about it, it just depends on your implementation. can you give a more complete example of what you are trying to do?

    >> While I don't think this is possible, I've been quite impressed by the flexibility of C++ and figure by asking about this, that there's a good chance there's a feature I don't know about that might help me in some way here or some other way to handle it.

    actually, I'd say your chances are about equal. but you'll learn in time.

    >>I've seriously considered, instead of having, say, 40 function calls for commands, to have one function that will process a string with the command and the arguments (which is quite easy and already done for my command line testing). I could do the same for getting output from the device by having one function call that takes a string with the name of the info needed as a parameter instead of providing 20-30 calls asking for each different piece of information, but I know programmers don't seem to like that kind of interface.

    imagine you are sampling a waveform at 44,100 hz. every single cycle commands are getting parsed, marshalled, and processed. there's no way that wouldn't affect performance. anyway, all that could be implemented as a separate class (template maybe). then you'd just need to define the hardware command processor in a separate header so that it could be included if desired.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM
  5. A question about constructors...
    By Wolve in forum C++ Programming
    Replies: 9
    Last Post: 05-04-2005, 04:24 PM