在重写方法中避免突变

时间:2013-07-04 17:31:10

标签: c++ oop

我有一个类似

的抽象类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>的构造函数。

我有什么选择?

1 个答案:

答案 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 =()之类的事情。我不确定从这一点开始,因为我不确定你想要什么。这是我最好的猜测,当然你可以自由修改它。