的解析我试图解析与嵌套结构的二进制文件格式。在程序的伪代码,该过程将如下这样:嵌套结构和对象模型
// A structure contains:
// tag | oneof(a, b, c) | oneof(oneof(aa, ab, ac), oneof(ba, bb, bc), oneof(ca, cb, cc))
PROCEDURE parse() {
RECORD read_type;
read_tag(read_type);
if (read_type == TYPE_A) {
read_a(read_type);
if (read_type == TYPE_AA) {
read_aa();
} else if (read_type == TYPE_AB) {
read_ab();
} else if (read_type == TYPE_AC) {
read_ac();
}
} else if (read_type == TYPE_B) {
// see above
} else if (read_type == TYPE_C) {
// see above
}
}
的外部结构例如AA不能在不脱离它的父对象A,而这又需要它的标签/标头解释上下文来解释。使用这些结构时,处理包含A的结构是有意义的,这些结构包含AA等,但不能是结构的A或AA部分。
我的问题是那么如何创建此过程的类模型。如果该结构是:
class Base;
class A: Base;
class B: Base;
class C: Base;
class AA: A;
class AB: A;
class AC: A;
// ...
在这种情况下,AA可能被理解为这样的:
AA::AA(): A() {
read_aa();
}
A::A(): Base() {
read_a();
}
Base::Base() {
read_tag();
}
然而,问题是,这是不可能知道的派生类对象,而不构建首先构造基础对象。这可以通过使用构造函数AA :: AA(A *)来复制构造其父项,但这看起来像是一种不必要的低效率。此外,这将需要一个外部工厂功能,诸如:
Base *read_object() {
Base *base = new Base();
if (b->tag_type == TYPE_A) {
A *a = new A(base);
if (a->tag_type == TYPE_AA) {
return new AA(a);
} else if (a->tag_type == TYPE_AB) {
// ...
} else if (a->tag_type == TYPE_AC) {
// ...
}
} else if (b->tag_type == TYPE_B) {
// ...
} else if (b->tag_type == TYPE_C) {
// ...
}
}
另一种选择是为具有指结构的子区域,如类:
class CompleteStructure;
class StructureA;
class StructureB;
class StructureC;
class StructureAA;
class StructureAB;
class StructureAC;
// ...
class CompleteStructure {
union {StructureA a, StructureB b, StructureC c} sub;
}
class StructureA {
CompleteStructure *parent;
union {StructureAA aa, StructureAB ab, StructureAC ac} sub;
}
class StructureAA {
StructureA *parent;
}
在这种情况下,该构造函数CompleteStructure :: CompleteStructure()会读取标记,然后构造StructureA,StructureB或StructureC中的一个,然后构造它自己的子结构。与此相关的问题是,每个子结构都需要明确引用其父项,以便“投射”层次并实现其方法/功能。
是这些方法比其他的更好的空间/时间效率和“清洁”的名词之一?有没有优越的第三种方法?
编辑: 要到下面的两个答案回应,问题是双方关于分析和对象行为。我最初的目标仅仅是从文件中读取结构,打印出它们的字段,然后按照相同的顺序将它们写回到磁盘。稍后,还会有额外的目标,例如查找A派生结构的所有实例并按特定字段对其进行排序或检查非法结构组合(例如,同时具有BA和BB)。
EDIT2: 这是我参考的一个结构(带有通用字段名称)的示例模式。 u8/16/32是指整数类型,sz是一个C字符串,大写名称是需要读取的字段,常量前缀为下划线。
DEF AA {
// Identifies and deliminates complete records.
TAG {
u32 SYNC_CODE = 0xFFFFFFFF;
}
// Metadata for high level identification of data.
A {
u32 TYPE = __TYPE_A;
u16 CATEGORY = __CATEGORY_1; // A defines the "category" of the following file data
u32 NUM_OF_KV_PAIRS;
for (int i = 0; i < NUM_OF_KV_PAIRS; ++i) { // unspecified metadata
sz KEY;
sz VALUE;
}
u8 HAS_EXTENSION_FLAG = true; // indicates presence of next record
if (!HAS_EXTENSION_FLAG) {
DEFAULT_PARAMS; // legacy
}
}
// Indicates a specific data layout and version.
AA {
u32 TYPE = __TYPE_AA;
u8[16] ACCESS_KEY;
u32 NUM_OFFSETS;
for (int i = 0; i < NUM_OFFSETS; ++i) {
// stuff
}
}
}
我没有得到_“与此相关的问题是,每个子结构都需要明确引用其父级以便”投射“层次结构”_您能详细说明一点吗?为什么一个子结构让我们说AA需要知道任何关于它的超级结构A的例子? –
AA中的字段指的是先前结构中的初始化结构来定义它们的语义。此外,为了类型安全,人们可能希望通过其特定类型来引用完整的结构,例如函数'process(AA a){do_something(a.complete_structure()); }'。 – user2363399
_HAS_EXTENSION_FLAG = true; //表示下一个记录的存在_这是关于AA结构的存在还是其他意义? –