C++ 11避免了"Call Super"代码的味道

Jas*_*ott 2 c++ lambda c++11

我正在寻找避免"召唤超级"代码气味的方法.当重新实现该函数时,需要子类来调用超类的虚函数版本时,会出现此代码异味.

class Base
{
    public:
        virtual void foo(){ ... }
}
class Derived : public Base
{
    public:
        virtual void foo(){ Base::foo();// required! ... }
}
Run Code Online (Sandbox Code Playgroud)

如果继承只有一层深,我可以使用模板方法

class Base
{
    public:
        void foo(){ ... ; foo_impl(); }
    protected:
        virtual void foo_impl(){}
}
class Derived : public Base
{
    protected:
        virtual void foo_impl(){ ... }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我需要继承Derived,我会回到我开始的地方.

我正在考虑注册方法.

class Base
{
    public:
        Base()
        {
            _registerCallback( [this](){ _baseFoo(); } );
        }
        void foo()
        {
            for( auto f : _callbacks )
                f();
        }
    protected:
        void registerCallback( std::function<void()> f )
        { 
            _callbacks << f;
        }
    private:
        void _baseFoo() { ... }
        std::list< std::function<void()> > _callbacks;
}
class Derived : public Base
{
    public:
        Derived()
        {
            _registerCallback( [this](){ _derivedFoo(); } );
        }
    private:
        virtual void _derivedFoo(){ ... }
}
Run Code Online (Sandbox Code Playgroud)

有更标准的方法吗?这种方法有任何问题或改进吗?

R S*_*ahu 5

用于

class Derived : public Base
{
    public:
        virtual void foo(){ Base::foo();// required! ... }
}
Run Code Online (Sandbox Code Playgroud)

是IMO的最佳方法.我不确定你为什么会考虑"代码味道".

  1. 在您建议的最后一种方法中,错误的可能性更高.
  2. 检测到未接来电更容易Base::foo().
  3. 如果所有归类都Base需要实现Base::foo(),那么公共代码就更好了Base::foo().派生类只需要进行调用.

对于它的价值,我们在我的工作中使用了这种模式,并且已经证明它已经使用了20多年.