CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Jul 2009
    Posts
    6

    [RESOLVED] C++ class separation question

    Hello,
    I'm working on modifying a current C++ library, libserial, and I'm trying to understand something. In its implementation, this library has a class, SerialPort, which contains all of the functions to access the serial port. However, there is another class, SerialPortImpl (which I'm assuming stands for "Serial Port Implementation") which acutally does all of the work: SerialPort simply has a private member SerialPortImpl object which it acts on. For example, to get the baud rate, the code looks like so:

    Code:
    int
    SerialPort::SetBaudRate( const BaudRate baudRate )
    {
        return mSerialPortImpl->SetBaudRate( baudRate ) ;
    }
    Why is this done? I know that this class double-buffers the serial port into its own buffer using a signal IO catch from the port, does this have something to do with it? I guess my question is; in general, why would someone do this?

    Thanks for the help.

  2. #2
    Join Date
    Jul 2009
    Posts
    6

    Re: C++ class separation question

    EDIT: The SerialPortImpl class inherits from a PosixSignalHandler class, whereas the SerialPort class does not. The definition looks like this:

    class SerialPort::SerialPortImpl : public PosixSignalHandler

    Maybe that helps.

  3. #3
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: C++ class separation question

    Not really enough details shown. Looks like SerialPort is some kind of container class for whatever mSerialPortImpl points to. That would be a "Has a" kind of relationship which is quite common.

  4. #4
    Join Date
    Jul 2009
    Posts
    6

    Re: C++ class separation question

    I undestand how container classes work, it just seems like SerialPort and SerialPortImpl do the exact same thing. It looks to me like the authors defined a class, defined another class that does pretty much the same thing, and has the first one call functions in the second one which could just as well be in the first one.

    Here's some more code examples to try and explain what I mean:

    SerialPort.h:
    Code:
    class SerialPort
    {
    public:
    ...
        /**
         * Set the parity type for the serial port.
         *
         * Returns -1 if success, 0 if error.
         */
        int
        SetParity( const Parity parityType ) throw() ;
    ...
    private:
    ...
        class SerialPortImpl ;
        SerialPortImpl* mSerialPortImpl ;
    SerialPort.cpp:
    Code:
    class SerialPort::SerialPortImpl : public PosixSignalHandler
    {
    public:
    ...
        int
        SetParity( const SerialPort::Parity parityType ) throw() ;
    private:
    ...
        std::queue<unsigned char> mInputBuffer ;
    }
    ...
    int
    SerialPort::SetParity( const Parity parityType ) throw()
    {
        return mSerialPortImpl->SetParity( parityType, myErrors ) ;
    }
    ...
    inline
    int
    SerialPort::SerialPortImpl::SetParity( const SerialPort::Parity parityType, portErrors& errors ) throw()
    {
        //
        // Make sure that the serial port is open.
        //
        if ( ! this->IsOpen() )
        {
            throw();
            return -1;
        }
        //
        // Get the current port settings.
        //
        termios port_settings ;
        if ( tcgetattr( mFileDescriptor,
                        &port_settings ) < 0 )
        {
            throw();
            return -1;
        }
        //
        // Set the parity type depending on the specified parameter.
        //
        switch( parityType )
        {
        case SerialPort::PARITY_EVEN:
            port_settings.c_cflag |= PARENB ;
            port_settings.c_cflag &= ~PARODD ;
            port_settings.c_iflag |= INPCK ;
            break ;
        case SerialPort::PARITY_ODD:
            port_settings.c_cflag |= ( PARENB | PARODD ) ;
            port_settings.c_iflag |= INPCK ;
            break ;
        case SerialPort::PARITY_NONE:
            port_settings.c_cflag &= ~(PARENB) ;
            port_settings.c_iflag |= IGNPAR ;
            break ;
        default:
            throw();
            break ;
        }
        //
        // Apply the modified port settings.
        //
        if ( tcsetattr( mFileDescriptor,
                        TCSANOW,
                        &port_settings ) < 0 )
        {
            throw();
        }
        return 0;
    }

  5. #5
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: C++ class separation question

    One reason I can think of why this might be done:

    If B is intended to be a base class which adds extra functionality to anything which inherits from it, then instead of defining any necessary members directly in B, they might be instead defined in C and B may simply contain a single C member.

    The advantage here is that classes deriving from B don't need to know any real details about how B works when (if) they define their copy constructor and operator=. In fact, they can still be allowed to auto-generate those things even if some of B's functionality would have required custom-defining them (since that gets foisted off on C).

  6. #6
    Join Date
    Jul 2009
    Posts
    6

    Re: C++ class separation question

    Thank you guys (and gals, possibly) for replying. I guess it's unfair for me to expect a perfect answer, since it's hard to give enough detail here without posting everything. Let me think out loud and see what people think. I don't need a perfect answer for this, I just didn't know if this code setup was familiar.

    This library has two basic classes: a SerialStream class and a SerialPort class. The SerialStream class provides unbuffered access to the operating system serial buffer of a specific port, for example ttyUSB0. It, like SerialPort, has a subclass, SerialStreamBuf. SerialStream has one pointer to this subclass in its private variables. This subclass provides all of the real functionality to the serial port, whereas the parent class SerialStream calls the functions in SerialStreamBuf. Since there aren't multiple types of SerialStream children, nor do I think there ever will be, this seems pointless to me.

    SerialPort, however, provides a double-buffered access to the port. It uses POSIX interrupts to fill its buffer whenever data comes in, and the class works on this buffer. Much like SerialStream, it has this subclass SerialPortImpl in which it calls these functions which are often even named the exact same as in SerialPort.

    Now for SerialStream, there's a little bit of extra functionality in the parent functions, but they could easily be combined into one function.

    @Lindley: I guess I don't fully understand your explanation. Sorry

  7. #7
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: C++ class separation question

    It looks like an implementation of the PIMPL pattern
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  8. #8
    Join Date
    Jul 2009
    Posts
    6

    Re: C++ class separation question

    Thank you, I thought it would be something like that. Makes sense, I'll have to read up on it....

    Thank you all for your help.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured