4

guys, I have a case that needs the child class needs to call its parent virtual function at first before call its override virtual function.

BaseClass::Draw()
{

}

ChildClass::Draw()
{
    BaseClass::Draw(); // BaseClass Draw must be called first.
}

GrandChildClass::Draw()
{
    ChildClass::Draw(); // ChildClass Draw must be called first.
}

I want to hide this behavior from clients. Is there pattern on this?

Thanks.

giggle
  • 1,911
  • 5
  • 21
  • 25
  • possible duplicate of [C++ : Call a base class method automatically?](http://stackoverflow.com/questions/3107974/c-call-a-base-class-method-automatically) – outis Apr 22 '12 at 00:23

1 Answers1

16

For simple cases you can use a second, private member function for the overrideable behavior:

class Base {
public:
    void Draw() { 
        // Base-class functionality here
        OverrideableDraw();
    }

private:
    virtual void OverrideableDraw() { }
};

class Derived : public Base {
private:
    virtual void OverrideableDraw() {
        // Derived-class functionality here
    }
};

For more complex hierarchies (e.g. where you have multiple levels of inheritance), this isn't possible since any derived class can override any virtual member function (there is no final in C++). Usually it is safe to assume that each derived class is doing the right thing. While I can think of a few times that I've run into issues because a derived class screwed up overriding, those cases were usually pretty straightforward to debug.

If you are really worried about it and really want to guarantee that base-class overrides are executed first, you could use something like this, though this is quite expensive (at least this naive implementation is quite expensive):

#include <functional>
#include <iostream>
#include <vector>

class Base {
public:

    Base() {
        RegisterDrawCallback(std::bind(&Base::DrawCallback, this));
    }

    void Draw() {
        for (auto it(drawCallbacks_.begin()); it != drawCallbacks_.end(); ++it)
            (*it)();
    }

protected:

    typedef std::function<void(void)> DrawCallbackType;
    typedef std::vector<DrawCallbackType> DrawSequence;

    void RegisterDrawCallback(DrawCallbackType f) {
        drawCallbacks_.push_back(f);
    }

private:

    void DrawCallback() { std::cout << "Base" << std::endl; }

    DrawSequence drawCallbacks_;
};

class Derived : public Base {
public:

    Derived() {
        RegisterDrawCallback(std::bind(&Derived::DrawCallback, this));
    }

private:

    void DrawCallback() { std::cout << "Derived" << std::endl; }
};

class DerivedDerived : public Derived {
public:

    DerivedDerived() {
        RegisterDrawCallback(std::bind(&DerivedDerived::DrawCallback, this));
    }

private:

    void DrawCallback() { std::cout << "DerivedDerived" << std::endl; }
};

[This is just one option; someone else can probably come up with a far more elegant solution. Personally, I'd just make sure the virtual member functions are well-documented and leave it at that.]

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 3
    In fact, [we should prefer to make virtual functions private, and provide public callers](http://www.gotw.ca/publications/mill18.htm). – GManNickG Apr 13 '11 at 04:22
  • That seems not work on multiple levels of derivation hierarchy. – giggle Apr 13 '11 at 04:24
  • 1
    Yup, [Non-Virtual Interface idiom](http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface). – Fred Larson Apr 13 '11 at 04:24