我有一个类似
的抽象类A
class A {
public:
virtual vector<char> marshall() = 0;
virtual void unmarshall(vector<char> raw) = 0;
};
从A
继承的类会覆盖这两种方法:特别是,unmarshall
会改变子类的内部状态。
e.g。
class B : public A {
int someImportantInt;
vector<char> marshall() {
vector<char> r;
r.push_back(someImportantInt);
return r;
}
void unmarshall(vector<char> raw) {
someImportantInt = raw[0];
}
};
现在,我认为变异是邪恶的,而且我们必须实例化B
,然后才调用unmarhsall
看起来像代码气味。
一个选项是拥有一个vector<char>
的构造函数,但我不知道如何强制子类这样做。
修改
构造函数方法的动机是,一旦调用了umarshall
,B的状态就不会改变。因此,我们可以从unmarshall
中移除A
,并使用带有B
的构造函数将其替换为vector<char>
。
即
class B : public A {
int someImportantInt;
B(const vector<char>& raw) : someImportantInt(raw[0]) {}
vector<char> marshall();
}
正如我所看到的,这里的问题是没有契约迫使子类声明一个带vector<char>
的构造函数。
我有什么选择?
答案 0 :(得分:0)
您可以使用执行编组和解组的Marshaller类模板。然后在类中使用Marshaller类型的数据成员而不是int。然后在Marshaller的构造函数中,您将初始化一个向量成员,因此没有类需要知道它。像这样:
template <class T>
class Marshaller {
T real_data;
vector<char> marshalled_data;
Marshaller ();
Marshaller (Marshaller&);
public:
Marshaller (T& t) :real_data(t) {
// Do whatever with marshalled_data.
}
void marshall () {
// Fill me in.
}
void unmarshall () {
// Fill this in.
}
vector<char> rawData () {
return marshalled_data;
}
bool isMarshalled () {
return marshalled_data.size() > 0;
}
T& data () {
return real_data;
}
};
class B {
Marshaller<int> someImportantInt;
public:
B () :someImportantInt(0) {}
B (int i) :someImportantInt(i) {}
int getImportantInt () {
return someImportantInt.data();
}
vector<char> getRawInt () {
return someImportantInt.raw data();
}
void unmarshall () {
someImportantInt.unmarshall();
}
};
我希望你理解这个想法足以给你一个起点。您可以向Marshaller添加更多函数,以便在数据编组或不编组时处理operator =()之类的事情。我不确定从这一点开始,因为我不确定你想要什么。这是我最好的猜测,当然你可以自由修改它。