3
struct Base {
  void foo(??? fn) {
    // do something with fn
  }
};

struct A : Base {
  A() : Base() { ... }
  void aa() { ... }
  void aaa() { ... }
};

struct B : Base {
  B() : Base() { ... }
  void bb() { ... }
};

int main() {
  A a, B b;
  a.foo(a.aa); // foo works with aa()
  a.foo(a.aaa); // foo works with aaa()
  b.foo(b.bb); // foo works with bb()
  return 0;
}

fnの子クラスのメンバ関数 (void を返し、パラメータなし) になりたいですBase。これは悪い設計のように思えます: 親は自分の子供のことを認識すべきではありません。ただし、機能をすべての子クラスに書き込むと、コードの重複が発生します。私は子供たちをできるだけ薄くしたいと思っています。

必要な機能を実現するための最適な設計は何ですか?

4

2 に答える 2

3

にこんにちはstd::function<void()>、これは void を返し、パラメーターを持たない関数を抽象化するタスクを正確に実行します。

編集:単純に仮想関数を使用しないのはなぜですか? お気に入り

struct Base {
private:
  virtual void fn() = 0;
public:
  void foo() {
    // do something with fn
  }
};

struct A : Base {
  A() : Base() { ... }
  void fn() { ... }
};

struct B : Base {
  B() : Base() { ... }
  void fn() { ... }
};

int main() {
  A a, B b;
  a.foo(); // foo works with aaa()
  b.foo(); // foo works with bb()
  return 0;
}

ただし、派生クラスごとにオーバーライド関数を 1 つだけに制限します。

于 2012-07-21T00:47:56.117 に答える
2

メソッドポインタを使用できます。

struct Base {
  template <typename D>
  void foo(void(D::*fn)()) {
    D *d = static_cast<D *>(this);
    (d->*(fn))();
  }
};

  A a; B b;
  a.foo(&A::aa); // foo works with aa()
  a.foo(&A::aaa); // foo works with aaa()
  b.foo(&B::bb); // foo works with bb()

より良い型の安全性dynamic_castが必要な場合は、を使用する必要がありますが、動的な型推論を行うことができるように、仮想デストラクタを追加する必要があります。

struct Base {
  virtual ~Base() {}
  template <typename D>
  void foo(void(D::*fn)()) {
    D *d = dynamic_cast<D *>(this);
    if (d == 0) throw 0;
    (d->*(fn))();
  }
};

  b.foo(&B::bb); // ok
  b.foo(&A::aa); // exception thrown
于 2012-07-21T00:55:02.500 に答える