如何自动化覆盖方法?
How to automatize overriding methods?
我想知道是否有任何棘手的方法可以以相同的方式覆盖所有 class 方法。例如,如何在大型 classes 中明智地实现复合模式?例如,当我得到这样的东西时:
class Foo{
virtual void work() = 0;
...
};
class FooLeaf : public Foo{
virtual void work() override{}
...
};
class FooComposite : public Foo{
std::vector<Foo *> foos;
virtual void work() override{
for (auto foo : foos){
foo->work();
}
}
...
};
重新实现一个方法是没有问题的。但是当方法的数量增加时,代码变得非常湿。我的意思是,我感觉不太好复制粘贴 foreach 循环,比方说,10 个方法。
如果所有方法都具有相同的签名,您可以使用方法指针:
class Foo{
public:
virtual void work() = 0;
virtual void rest() = 0;
};
class FooComposite : public Foo {
std::vector<Foo *> foos;
void do_all(void (Foo::*method)()) {
for (auto foo : foos) {
(foo->*method)();
}
}
void work() override {
do_all(&Foo::work);
}
void rest() override {
do_all(&Foo::rest);
}
};
如果您只想摆脱循环,但不介意重复方法名称,则可以将迭代(以及可能的任何错误处理)封装在 Composite
模板中,然后您可以使用 lambda 将调用转发到组合的每个元素。
template <typename ElementType>
class Composite : public ElementType {
private:
std::vector<ElementType*> container;
protected:
template < typename Fn>
auto apply (Fn && fn) {
for (auto& e : container) {
fn(*e);
}
}
};
class Foo{
public:
virtual void work() = 0;
};
class FooLeaf : public Foo{
virtual void work() override { }
};
class FooComposite : public Composite<Foo> {
virtual void work() override {
return apply([](Foo& f){f.work();});
}
};
更好的是,您可以通过 Composite class 模板将添加的元素封装到复合中,这可以说是属于它的地方。 apply
的实现依赖于一些 C++14 类型推导特性,使其更易于编写和查看。
我想知道是否有任何棘手的方法可以以相同的方式覆盖所有 class 方法。例如,如何在大型 classes 中明智地实现复合模式?例如,当我得到这样的东西时:
class Foo{
virtual void work() = 0;
...
};
class FooLeaf : public Foo{
virtual void work() override{}
...
};
class FooComposite : public Foo{
std::vector<Foo *> foos;
virtual void work() override{
for (auto foo : foos){
foo->work();
}
}
...
};
重新实现一个方法是没有问题的。但是当方法的数量增加时,代码变得非常湿。我的意思是,我感觉不太好复制粘贴 foreach 循环,比方说,10 个方法。
如果所有方法都具有相同的签名,您可以使用方法指针:
class Foo{
public:
virtual void work() = 0;
virtual void rest() = 0;
};
class FooComposite : public Foo {
std::vector<Foo *> foos;
void do_all(void (Foo::*method)()) {
for (auto foo : foos) {
(foo->*method)();
}
}
void work() override {
do_all(&Foo::work);
}
void rest() override {
do_all(&Foo::rest);
}
};
如果您只想摆脱循环,但不介意重复方法名称,则可以将迭代(以及可能的任何错误处理)封装在 Composite
模板中,然后您可以使用 lambda 将调用转发到组合的每个元素。
template <typename ElementType>
class Composite : public ElementType {
private:
std::vector<ElementType*> container;
protected:
template < typename Fn>
auto apply (Fn && fn) {
for (auto& e : container) {
fn(*e);
}
}
};
class Foo{
public:
virtual void work() = 0;
};
class FooLeaf : public Foo{
virtual void work() override { }
};
class FooComposite : public Composite<Foo> {
virtual void work() override {
return apply([](Foo& f){f.work();});
}
};
更好的是,您可以通过 Composite class 模板将添加的元素封装到复合中,这可以说是属于它的地方。 apply
的实现依赖于一些 C++14 类型推导特性,使其更易于编写和查看。