假设我有一个我不拥有的类:DataBuffer。它提供了各种get成员函数:
get(uint8_t *value);
get(uint16_t *value);
...
从包含在此缓冲区中的结构中读取时,我知道字段的顺序和大小,并且我想减少未来代码更改导致错误的机会:
struct Record
{
uint16_t Header;
uint16_t Content;
}
void ReadIntoRecord(Record* r)
{
DataBuffer buf( initialized from the network with bytes )
buf.get(&r->Header); // Good!
buf.get(&r->Content);
}
然后有人在写入之前检查更改以对标头执行某些操作:
uint8_t customHeader;
buf.get(&customHeader); // Wrong, stopped reading after only 1 byte
r->Header = customHeader + 1;
buf.get(&r->Content); // now we're reading from the wrong part of the buffer.
以下是一种可以接受的方式来强化代码以防止更改?请记住,我不能将函数名称更改为 getByte、getUShort 等。我可以从 DataBuffer 继承,但这似乎有点过头了。
buf.get(static_cast<uint16_t*>(&r->Header)); // compiler will catch incorrect variable type
buf.get(static_cast<uint16_t*>(&r->Content))
更新了不安全的遗留代码示例:
float dummy_float;
uint32_t dummy32;
uint16_t dummy16;
uint8_t dummy8;
uint16_t headTypeTemp;
buf.get(static_cast<uint16_t*>(&headTypeTemp));
m_headType = HeadType(headTypeTemp);
buf.get(static_cast<uint8_t*>(&hid));
buf.get(m_Name);
buf.get(m_SerialNumber);
float start;
buf.get(static_cast<float*>(&start));
float stop;
buf.get(static_cast<float*>(&stop));
buf.get(static_cast<float*>(&dummy_float));
setStuffA(dummy_float);
buf.get(static_cast<uint16_t*>(&dummy16));
setStuffB(float(dummy16)/1000);
buf.get(static_cast<uint8_t*>(&dummy8)); //reserved
buf.get(static_cast<uint32_t*>(&dummy32));
Entries().setStart( dummy32 );
buf.get(static_cast<uint32_t*>(&dummy32));
Entries().setStop( dummy32 );
buf.get(static_cast<float*>(&dummy_float));
Entries().setMoreStuff( dummy_float );
uint32_t datalength;
buf.get(static_cast<uint32_t*>(&datalength));
Entries().data().setLength(datalength);
RetVal ret = ReturnCode::SUCCESS;
Entry* data_ptr = Entries().data().data();
for (unsigned int i = 0; i < datalength && ret == ReturnCode::SUCCESS; i++)
{
ret = buf.get(static_cast<float*>(&dummy_float));
data_ptr[i].FieldA = dummy_float;
}
for (unsigned int i = 0; i < datalength && ret == ReturnCode::SUCCESS; i++)
{
ret = buf.get(static_cast<float*>(&dummy_float));
data_ptr[i].FieldB = dummy_float;
}
// Read in the normalization vector
Util::SimpleVector<float> norm;
buf.get(static_cast<uint32_t*>(&datalength));
norm.setLength(datalength);
for (unsigned int i=0; i<datalength; i++)
{
norm[i] = buf.getFloat();
}
setNormalization(norm);
return ReturnCode::SUCCESS;
}