具有公共成员对象的班级组成
Class composition with public member objects
我正在尝试找出设计我的程序功能的最佳方法。
该程序的主要组成部分是相机类。该相机对象表示程序用户界面与真实摄像机的界面,该摄像头通过框架抓取卡将其连接到计算机。相机类可以链接到框架抓取器,启动和停止获取,还可以突变/访问许多不同的相机属性。当我说很多时,我谈论的是超过250个独特的命令。每个唯一的命令都通过将串行串通过框架夹发出到物理摄像头来发出相机。每个命令都可以被认为是三种类型之一。动作,查询和值。
一个动作命令是不需要等等的东西
查询是您可以获得但不设置的东西,通常与值相关。例如"温度=?"," sernum =?"," maxframerate =?"命令会导致相机发送回到信息。这些值无法突变,因此"温度= 20"会导致错误。
值是您可以获得和设置通常与值关联的值。例如" Framerate = 30"answers" Framerate =?"是两个唯一的命令,但我认为基本字符串" Framerate"是一种值命令类型,因为它可以被突变和访问。
250个唯一的命令可以减少到约100个相机,相机Querquerys和Cameravalues。我没有在相机类中使用250种方法,而是想组成命令对象,而不是单个设置器,获取器和操作。命令字符串可以在构造函数中提供,也可以用设置器重置。然后,我可以撰写一个包含所有可用命令的cameracommands对象,并作为我相机的公共成员提供。
//CameraAction.h =============================================
class CameraAction {
public:
CameraAction(std::string commandString, SerialInterface* serialInterface);
void operator()() { _serialInterface->sendString(_commandString); }
private:
SerialInterface* _serialInterface;
std::string _commandString;
};
//CameraValue.h =====================================================
class CameraValue {
public:
CameraValue(std::string commandString, double min, double max, SerialInterface* serialInterface);
void set(double value)
{
if(value > _maxValue) { throw std::runtime_error("value too high"); }
if(value < _minValue) { throw std::runtime_error("value too low"); }
std::string valueString = std::to_string(value);
_serialInterface->sendString(_commandString + "=" + valueString);
}
double get()
{
std::string valueString = _serialInterface->sendString(_commandString + "=?");
return atof(valueString.c_str());
}
private:
SerialInterface* _serialInterface;
std::string _commandString;
double _minValue;
double _maxValue;
};
//CameraCommands.h ===================================================
class CameraCommands {
public:
CameraCommands();
CameraAction reset;
CameraQuery temperature;
CameraValue framerate;
CameraValue sensitivity;
//... >100 more of these guys
};
//Camera.h ===========================================================
class Camera {
public:
Camera();
CameraCommands cmd;
void startAcquisition();
void stopAcquisition();
void setDataBuffer(void* buffer);
void setOtherThing(int thing);
};
以便用户可以做类似的事情:
Camera myCamera;
myCamera.cmd.reset();
myCamera.cmd.framerate.set(30);
myCamera.cmd.sensitivity.set(95);
double temperature = myCamera.cmd.temperature.get();
myCamera.startAcquisition();
等...
这里的主要问题是我正在揭露公共成员变量,这应该是一个巨大的禁忌。是我当前的对象设计逻辑,还是我应该简单地实现250个固定器和盖特特,还有100个固定器和Getters来突变最小和最大可设置值。
对我来说这似乎是kludgey,因为与用户命令无关的相机对象相关的固定器/获取器。用户界面提供方法(CMD)的范围是很好的,以便用户知道是否在相机中进行物理突变,还是只是在程序化对象中突变(其他方法)。有什么更好的方法设计我的程序吗?
您基本上描述了一个有趣的层次结构:
Command
-> Query
-> Value
。
- a
Command
保留是命令文本的字符串;它还可以为其孩子提供protected
Send()
方法。 - a
Query
还可以立即持有(protected
)int
变量(或其他可以立即get()
和/或operator int()
),或者来自相机中的query()
; - A
Value
将set()
和/或operator =(int)
命令添加到Query
。
Value
的构造函数(特别是)可以具有min
和max
。
Camera
对象可以具有许多public
成员:
class Camera {
private: // Classes that no-one else can have!
class Command; friend Command;
#include "Camera.Command.inc"
class Query; friend Query;
#include "Camera.Query.inc"
class Value; friend Value;
#include "Camera.Value.inc"
public: // Variables using above classes
Command reset;
Command open; // Maybe make this one private, for friends?
Command close; // Ditto?
Query temperature;
Query sernum;
Query maxFrameRate;
Value frameRate;
private: // Variables
SerialPort port; // Allow Command and co. access to this
}; // Camera
通过这样组织,然后:
- 变量的用户无法提出不可能的请求 - 没有任何方法;
-
query()
和set()
方法隐藏了与物理摄像机接口的机制。
您会注意到我已经在Camera
类的中间添加了#include "Camera.XXX.inc"
。注意:
- 它不会用这些子类的定义来混乱相机类 - 但是C 编译器需要它们在使用它们之前需要它们,因此您需要将它们放在那里。如果您想知道他们的工作,请打开文件!
- 我给了他们
.inc
扩展程序,因为它们在.h
文件中"包括":它们不单独作为自己的标头文件。
您可以使用一个或多个结构来分组"设置",然后公开一种方法来设置它们:
typedef struct settings{
int setting1;
int setting2;
}MySettings;
class Myclass{
private :
int setting1;
int setting2;
public Myclass(MySettigs *settings)
{
if(null != settings){
setting1=settings->setting1;
setting2=settings->setting2;
}
}
public void ChangeSettings (MySettings *setting){
if(null != settings)
{
setting1=settings->setting1;
setting2=settings->setting2;
}
}
public void TakeSettings (MySettigs *settings){
[copy local variables into the passed struct]
}
我强烈建议在对象"操作"时更改设置时要小心。
在您提到的设计中,我不认为通过构图展示公共成员是一个很大的禁忌。
公开公共成员时,大否-NO是不安全的访问您的课程内部。
一个示例将允许公众访问CameraValue::_maxValue
。用户可以将该值更改为任何事物,从而导致各种不确定的行为。
是否由我设计,我不会有CameraCommands
成员,因为从外观上看,它不会添加其他任何东西,而是间接级别。
我要么将所有CameraAction
和CameraValue
成员作为相机类的一部分,要么继承。
类似的东西:
将CameraCommands
合并到Camera
中:
class Camera
{
public:
Camera();
CameraAction reset;
CameraQuery temperature;
CameraValue framerate;
CameraValue sensitivity;
//... >100 more of these guys
void startAcquisition();
void stopAcquisition();
void setDataBuffer(void* buffer);
void setOtherThing(int thing);
};
将CameraCommands
继承到Camera
:
class Camera : public CameraCommands
{
public:
Camera();
void startAcquisition();
void stopAcquisition();
void setDataBuffer(void* buffer);
void setOtherThing(int thing);
};
您甚至可以为CameraValue
等提供一些操作员,以便您可以通过分配设置值(operator=
),并通过隐式转换(operator T
)或删除性(operator*
)获取值:
template<typename T>
class CameraValue
{
public
CameraValue(SerialInterface*, std::string cmd);
CameraValue& operator=(const T& val)
{
_val = val;
std::string val_str = std::to_string(_val);
_ser_ifc->sendString(_cmd + "=" + val_str);
}
const T& get() const
{
return _val;
}
// implicit access to _val
operator const T&() const
{
return _val;
}
// dereference operator to access _val
const T& operator*() const
{
return _val;
}
private:
T _val;
SerialInterface* _ser_ifc;
std::string _cmd;
};
然后在类中使用CameraValue
如下:
using CameraFramerate = CameraValue<int>;
CameraFramerate framerate;
上述技术提供(IMO)Camera
的更合并的用法,例如以下内容:
Camera camera;
// setting values
camera.framerate = 30;
camera.sensitivity = 95;
// getting values
int framerate = camera.framerate; // uses operator T&()
int framerate = *camera.framerate; // uses operator*()
这里的关键是Camera::framerate
等不允许任何可以以不确定和/或不安全方式更改相机类的内部状态的访问。
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 在运行时有条件地删除类成员或跳过调用该成员对象的构造函数
- C++是否有定义的方法来传递指向类的成员对象的成员函数的指针
- (2 问题)"类"类型重新定义(即使 #pragma 一次),以及静态函数内的静态成员对象初始化?
- 声明成员对象而不调用其默认构造函数
- 指向成员对象的指针 - 中断线程
- 是否有更好的方法来封装成员对象可以访问的共享存储池?
- 应该在成员对象上调用析构函数
- 调用成员对象的构造函数
- 将 const 类型引用对象注册为类成员对象C++
- 修改类 c++ 中的成员对象
- 从成员对象调用方法
- 从对象调用成员对象,错误:引用非常量值的初始值必须是左值
- 构造函数,成员对象
- 不能使外部类成为内部类内的成员对象
- 使用从另一个类继承的类的对象初始化成员对象
- 如何避免需要在初始化列表中初始化成员对象
- 初始化具有参数的类成员对象的正确方法
- 将指针添加到成员对象中的指针动态阵列
- C 将成员对象函数分配给类成员功能