How to declare structures of data that should only be used in a certain context, C++
I'm having a rather general design problem and would like to solve it nicely. I'm writing remote control drivers in an embedded C++ project. There will be two types of remote control: joystick or radio. As I'd like the actual remote controller used to be transparent to an user-programmer, I'm also providing a base class for the two. So I'm going to have:
class RemoteControl {};
class JoystickControl : public RemoteControl {};
class RadioControl : public RemoteControl {};
I'd like RemoteContol to just have one public method: RemoteControl.getInput()
. This method should return a structure of data in common format, eg. RCInput
, so the above method's declaration would be:
class RemoteContol {
virtual RCInput getInput();
};
Now, what's the best way to implement RCInput to be able to pass it to other classes' objects? I thought an inner class / structure might be a solution, but I never used it yet so can someone please provide an example of implementation and usage?
Thanks in advance.
EDIT: What I did before was (could be references, this is not important at the moment):
typedef struct {
int a;
int b;
} R开发者_运维问答CInput;
class RemoteContol {
public:
virtual RCInput getInput() { return rcInput; }
private:
RCInput rcInput;
};
But I thought this way I'm allowing users to create their own structures of type RCInput also not related to RemoteControl, so I was looking for a better design. But maybe there isn't any.
It looks that RCInput
is going to be just data, so you can lay it out like that:
RCInput.h
file
class RCInput
{
public:
RCInput(double x, double y, double z);
double x() const;
double y() const;
double z() const;
private:
double m_x;
double m_y;
double m_z;
};
RCInput.cpp
file:
RCInput::RCInput(double x, double y, double z)
: m_x(x), m_y(y), m_z(z)
{
}
double RCInput::x() const
{
return m_x;
}
double RCInput::y() const
{
return m_y;
}
double RCInput::z() const
{
return m_z;
}
Don't make it a nested class, put it in its own header file. This way the clients which use the inputs do not depend physically on the RemoteControl
class header file. In my experience, nested classes are usually an unnecessary complication, they should be best avoided unless really necessary (e.g. iterators in containers).
Also, don't yield to the temptation of making RCInput
a struct with public data. You will lose all control over data accesses and creation of data, if you do so (no access logging in getters, no data validation in constructor, no place to set a debugger breakpoint). Remember that forward declaring a class/struct means that some other piece of code will need to be changed if you later decide to turn a struct
into class
, i.e. instead of
struct RCInput;
you will have to write
class RCInput;
It's better to make it a class from day 1.
If you worry about performance, you can inline the getters.
If you want to store RCInput
in containers, add a public default constructor.
If you want to control who can create RCInput
, make the constructor private and declare the creating classes as friends (but that makes storing it in containers difficult).
精彩评论