-
July 20th, 2009, 01:17 PM
#1
[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.
-
July 20th, 2009, 01:22 PM
#2
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.
-
July 20th, 2009, 01:23 PM
#3
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.
-
July 20th, 2009, 01:46 PM
#4
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;
}
-
July 20th, 2009, 02:12 PM
#5
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).
-
July 20th, 2009, 02:26 PM
#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
-
July 21st, 2009, 05:06 AM
#7
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
-
July 21st, 2009, 07:42 AM
#8
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|