Force execution of parent's method before chil

2019-08-05 07:27发布

问题:

I'm working on a c++ app and I'm facing a problem: I have a class B derived from the abstract class A that has some event handling methods. A third class C is derived from B and must reimplement some of B methods. Is there a way to implicitly call B's method before calling C's one?

Class diagram:

class A
{
    virtual void OnKeyPress(event e)=0;
};
class B : public A
{
    virtual void OnKeyPress(event e)
    {
    print("Keypressed: "+e)
    };
};
class C : public B
{
    void OnKeyPress(event e)
    {
    //DoSomething
    }
}

One of the workaround I figured out is to call the parent's method from C using, say, B::foo() inside C::foo(). This works but it is up to the developer to remember to add the call in the method's body.

The other is to define a new virtual method that the child will override and that the parent will call inside its "OnKeyPress" method.

Thank you, 3mpty.

回答1:

You have to explicitly call the base class method.

class C : public B
{
    virtual void OnKeyPress(event e)
    {
        B::OnKeyPress(e);
        // Do stuff
    }
};

Just re-read your question.....

Best thing to do is to implement method in B that lastly calls an additional protected virtual method to be implemented by C.

i.e.

class B : public A
{
  protected:
       virtual void AdditionalKeyStuff(event e) { }

  public:

    virtual void OnKeyPress(event e)
    {
        // Do B Stuff

        // Finally give decendants a go.
        AdditionalKeyStuff(e)
    }
};


class C : public B
{
  protected:

    virtual void AdditionalKeyStuff(event e)
    {
        // Do only C stuff
    }
};

And you could make the AdditionalKeyStuff(...) in B pure virtual if you want to force any decendants to override it.



回答2:

No. There's no way to have this implicit call.

Plus you gave the two ways to do this in your question!



回答3:

"Almost" the same you have in the question, but separating public class interface and inheritance interface - mighty useful for all kinds of instrumentation:

class A
{
private:

    virtual void DoOnKeyPress( event ) = 0;

    void PreKeyPress( event ) { /* do something */ }
    void PostKeyPress( event ) { /* do something */ }

public:

    virtual ~A() {}

    void OnKeyPress( event e )
    {
        PreKeyPress( e );
        DoOnKeyPress( e );
        PostKeyPress( e );
    }
};

class B : public A
{
private:

    virtual void DoOnKeyPress( event e )
    {
        std::cout << "Keypressed: " << e << std::endl;
    }
};


回答4:

That is only possible when the method in question is a constructor, and then only happens when the object is constructed. If you can arrange for all the necessary work to be in a constructor you may have something, but it would be very hard to generalise that solution.