【问题标题】:Cascade calls on override virtual methods覆盖虚拟方法的级联调用
【发布时间】:2019-05-22 14:42:23
【问题描述】:

我正在开发一个大型软件,该软件严重依赖调用超级反模式。

基本上,接口定义了一个init() 虚拟方法,然后在继承它的每个类中重写该方法。 当在类上调用 init() 时,每个重载的 init 方法都会级联,从基类到顶级子类,以及介于两者之间。

但用户必须自己调用其直接父级的init() 方法,导致代码如下:

class myClass : public Base
{
    virtual void init()
    {
        Parent::Init() // often forgotten, or misplaced by the developer
        // Do some init stuff
    }
}

对此的替代方法通常是使用委托。 Base 类在 init 中有一些事情要做,即在 Base 中声明为 final,并将其中的一部分委托给继承类应覆盖的 onInit() 方法。但这并没有像我希望的那样级联对所有父类的调用。

我首先实现的替代方法是委托方法的变体。子类和 Base 都实现了 onInit()init() 方法。 init() 调用Parent::init(),然后调用onInit() 本身,并使用模板元编程和宏自动生成。 onInit() 包含特定于类的代码。

# define DELEGATE(T, Parent) \
     void init() override { Parent::init(); T::onInit(); }

struct Base
{
    virtual void init() { Base::onInit(); }
    virtual void onInit() {}
};

struct A : public Base
{
     DELEGATE(A, Base)
     void onInit() override { /* MyCustom code for A */ }
};

struct B : public A
{
     DELEGATE(B, A)
     void onInit() override { /* MyCustom code for B */ }
};

这很好用.. 除了多重继承变得一团糟,即使处理,菱形继承也会导致重复调用的问题。

这让我想知道:我不可能是唯一一个在寻找解决我的问题的设计模式的人,stackoverflow 社区必须知道这一点:)

你有没有遇到过这样的设计模式? 我真的很期待你的想法!

【问题讨论】:

  • 我不明白。这实际上不是两次调用派生类的onInit 吗?一次来自Baseinit,一次来自DELEGATE 宏的扩展。
  • 对不起,你是对的。 Base::init() 应该在 onInit() 上调用 Base::onInit() 我修复了我的帖子,对此感到抱歉
  • 您可以使用 CRTP,而不是 MACRO(因此可以轻松处理多重继承)。
  • 对于重复调用,您可以传递一个std::set<std::type_index> 来有条件地调用onInit
  • 很遗憾,proposal for std::bases and std::direct_bases 已被拒绝。

标签: c++ design-patterns super anti-patterns


【解决方案1】:

这就是我要保护自己不要忘记在儿童课程中覆盖的内容。这是简单的模板方法设计模式实现:

class Base {
public:
    void init() {
        //base init steps
        childInit();
    }

private:
    virtual void childInit() = 0;
};

class Child : public Base {
private:
    void childInit() override { /*init the child*/}
};

【讨论】:

  • 感谢您的回答@bartop 但这对我来说不起作用,因为我希望所有孩子和孩子的孩子都能在级联中调用他们的 init() 方法。例如,如果我有一个继承 Base 的 A 类、一个继承 A 的 B 类和一个继承 B 的 C 类,我希望在 C 上调用 init() 来执行以下调用: Base::init(); A::init(): B::init(); C::init()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-19
  • 2014-03-18
  • 2012-10-26
  • 1970-01-01
  • 2011-05-21
  • 1970-01-01
相关资源
最近更新 更多