在我正在开发的嵌入式应用程序中,我经常需要打包来自多个不同对象的数据,以便通过串行端口发送出去。同样,数据从串行端口进入,需要写入多个不同的对象。
出于兼容性原因,数据包中的数据顺序不允许与一个对象关联的所有数据连续放置在数据包中。所以我不能轻易地矢量化等来自每个对象的数据,然后将所有这些数据放在一个数据包中。
我可以使用数据包类用来创建/解码传输/接收的数据包的大量 getters/mutators 来实现适当的功能。但这似乎不是很优雅。
我可以使数据包类成为它从中提取数据/向其中写入数据的类的友元,但我总是被告知要避免使用友元类,因为那样会违反面向对象的原则。
理想情况下,处理实际应用程序的类不会知道有关数据包类的任何信息(并且不必专门为其提供 getter/mutator),并且如果数据包在更新之间出现,它们只会有新数据。
我想也许我可以在启动时将指向相关成员变量的引用或指针传递给数据包类,但这也很棘手,因为所有成员的大小都不相同。也许我也可以传递尺寸信息?是否有一种方法可以将指向成员的空指针列表和成员对的大小向量化,以便数据包类不需要为其构造函数提供大量参数?
我不确定我对这个问题的描述有多好,但如果有帮助,我当然可以提供澄清和更多信息。非常感谢任何想法。
当前tx数据包类的缩写示例:
class PacketTx {
private:
uint8_t buffer[MAX_PACKET_SIZE]; // MAX_PACKET_SIZE is 200
public:
PacketTx(object1 *firstObject,
object2 *secondObject,
object3 *thirdObject
// ...etc...
)
void sendPacket(void);
};
void PacketTx::sendPacket(void) {
uint32_t i = 0;
int16_t tempVar1 = firstObject->getVar1();
uint32_t tempVar2 = secondObject->getVar2();
uint8_t tempVar3 = firstObject->getVar3();
int32_t tempVar4 = thirdObject->getVar4();
// ...etc...
memcpy(buffer + i, &tempVar1, sizeof(tempVar1));
i += sizeof(tempVar1);
memcpy(buffer + i, &tempVar2, sizeof(tempVar2));
i += sizeof(tempVar2);
memcpy(buffer + i, &tempVar3, sizeof(tempVar3));
i += sizeof(tempVar3);
memcpy(buffer + i), &tempVar4, sizeof(tempVar4));
i += sizeof(tempVar4);
// ...etc...
for(uint32_t j = 0; j < i; ++j)
putc(static_cast<char>(buffer[i]));
}
这个例子不包括 header 、校验和等,但它应该给出一个让我头疼的问题的基本概念。
最佳答案
所以如果我知道你有一些 C 类,它有任意数量的成员,需要以任意顺序写入缓冲区。然后相同的机制反过来发生。
串行 -> Packet.buffer() -> 对象(和反向)
我最初的想法是使用 boost::tuple
并让类型与数据包中的数据顺序相对应。 (但是元组中可能有 50 多个成员/条目,这可能是一个很大的编译时间命中)
例如
tuple<float, int, std::string> a(1.0f, 2, std::string("Some Words");
ostr << a;
这还需要您的类将元组作为参数并从数据中填充条目。因此,与其写入缓冲区,还不如对元组中的字段进行枚举,这样就可以编写“漂亮”的代码:
enum Fields {Price,Amount,Reason};
typedef boost::tuple<...> MyTuple;
void MyClass::getData( MyTuple& t )
{
t<Price>() = mPrice;
t<Amount>() = mAmount;
t<Reason>() = mSomeReason;
}
注意也可以反向工作。
不确定这是否完全符合您尝试做的事情,但它可能会引发一些新想法?
关于c++ - 没有大量 getter/mutator 的优雅的面向对象的成员访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13087918/