有没有一种方法可以强制调用被覆盖的方法?

3
代码场景如下:
class ParentClass {
    void foo();
    virtual void doSomething() { foo(); }
};

class ChildClass : public ParentClass {
    virtual void doSomething();
};

现在,有没有一种方法可以强制子类调用父类的doSomething()函数呢?假设调用foo()非常重要,并且每次调用doSomething()时都应该调用它。当然,子类可以调用ParentClass :: doSomething(),但这似乎有些“冒险”,因为这并不是强制性的。

我想出了一个“笨拙”的解决方案,大概像这样:

class ParentClass {
    void foo();
    void doSomething() final {foo(); doSomethingChild(); }
    virtual void doSomethingChild() = 0;
};

class ChildClass : public ParentClass {
    virtual void doSomethingChild();
};

这样一来,子类必须进行实现,并且始终会调用foo(),但是该方法已不再相同。是否有更加优雅的解决方案?


2
你的“不太优雅”的解决方案被称为模板方法模式。这是一个完全可以解决你的问题的好方案。 - Tobias Brandt
我非常确定你现在的做法就是正确的做法。 - Galik
@TobiasBrandt 由于某种原因,它仍然让我感觉像个罪人。 :p - manabreak
2个回答

3

这不是一个丑陋的解决方案,而是您自己发现的非虚拟接口习惯用法(或模板方法模式)。

通过定义一个调用虚函数(以及其他内容)的非虚函数,您强制每个类实现其非虚函数的行为。实现仅允许修改此行为的一部分,即调用虚函数。

通常这样做:

class Base {
public:
    void foo() {
        //do stuff
        fooImpl();
        //do other stuff
    }
private:
    virtual void fooImpl(); //pure or not
};

class Derived : public Base {
private:
    virtual void fooImpl(){
    // Implement or change fooImpl behavior
    }
};

使非虚拟公共和虚拟私有也确保了没有人可以在这些类上调用 fooImpl,这正是您想要的,因为您需要在调用 fooImpl 之前和/或之后执行一些操作。

0

让我们看看这是否可行:

class parent {
     void foo() {...}
     virtual void doFinal() {...}
     void doSomething (){foo(); doFinal();}
}

class child {
    virtual void doFinal() {...}
}

所以你可以重新实现 doFinal 并使用 doSmthing。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接