vendredi 3 février 2017

C++ 11 avoiding "Call Super" code smell

I'm looking for ways to avoid the "call super" code smell. This code smell is present when a subclass is required to invoke the super class's version of a virtual function when re-implementing that function.

class Base
{
    public:
        virtual void foo(){ ... }
}
class Derived : public Base
{
    public:
        virtual void foo(){ Base::foo();// required! ... }
}

If inheritance went only a single layer deep, I could use the template method

class Base
{
    public:
        void foo(){ ... ; foo_impl(); }
    protected:
        virtual void foo_impl(){}
}
class Derived : public Base
{
    protected:
        virtual void foo_impl(){ ... }
}

But if I need to subclass Derived, I'm back where I started.

I'm considering a registration approach.

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(){ ... }
}

Is there a more standard approach? Any problems with or improvements to this approach?

Aucun commentaire:

Enregistrer un commentaire