How to force child same virtual function call its parent virtual function first

后端 未结 1 1164
抹茶落季
抹茶落季 2020-12-06 20:21

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(         


        
相关标签:
1条回答
  • 2020-12-06 20:51

    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.]

    0 讨论(0)
提交回复
热议问题