如何强制子相同的虚函数首先调用其父虚函数

时间:2011-04-13 04:18:24

标签: c++ design-patterns polymorphism oop

人, 我有一个案例需要子类在调用其覆盖虚函数之前首先需要调用其父虚函数。

BaseClass::Draw()
{

}

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

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

我想从客户端隐藏此行为。这有模式吗?

感谢。

1 个答案:

答案 0 :(得分:16)

对于简单的情况,您可以使用第二个私有成员函数来处理可重写行为:

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
    }
};

对于更复杂的层次结构(例如,您有多个继承级别),这是不可能的,因为任何派生类都可以覆盖任何虚拟成员函数(C ++中没有final)。通常可以安全地假设每个派生类都在做正确的事情。虽然我可以想到几次我遇到了问题,因为派生类搞砸了覆盖,但这些情况通常很容易调试。

如果你真的很担心它并且真的想保证首先执行基类覆盖,你可以使用类似的东西,虽然这是非常昂贵的(至少这个天真的实现非常昂贵):

#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; }
};

[这只是一个选择;其他人可能会想出一个更优雅的解决方案。就个人而言,我只是确保虚拟成员函数有详细记录并留在那里。]