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;
}

I'd like fn to be some member function (returns void, no parameters) of child class of Base. It seems like a bad design: parents should not be aware of their childs. However, to write the functionality into every child class leads to code duplicity. I'd like to have the childs as thin as possible.

What would be the best design to achieve the desired functionality?

有帮助吗?

解决方案

You can use method pointers.

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()

If you want better type safety, you should use dynamic_cast, but you need to add a virtual destructor so that the dynamic type inference can be made:

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

其他提示

Say hello to std::function<void()>, which performs exactly the task of abstracting any function which returns void and has no parameters.

Edit: Why not simply use a virtual function? Like

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;
}

Does limit you to only one overriding function per derived class, though.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top