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

标签 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.
}

我想对客户隐藏此行为。这上面有图案吗?

谢谢。

最佳答案

对于简单的情况,您可以使用第二个私有(private)成员函数来实现可覆盖的行为:

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

[这只是一个选项;其他人可能会想出一个更优雅的解决方案。就我个人而言,我只是确保虚拟成员函数有详细的文档记录,然后就此打住。]

关于c++ - 如何强制子相同的虚函数首先调用其父虚函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5644338/

相关文章:

C++:编译时检查匹配的函数调用对?

c# - 为什么 C# 的编译速度比 C++ 快得多?

android - iOS 中的 subview Controller 是否与 Android 中的 fragment 相同?

c++ - 在 C++ 中返回虚类的派生类

c++ - 调用虚函数时继承类 "invalid pointer error"

f# - F# "remove a lot of subtle bug"如何来自 OCaml "+"?

c++ - XercesDOMParser 和 XIncludes

c++ - 使用字符串文字初始化非常量参数

javascript - javascript 中的数据上下文交互 (DCI) 和事件编程

orm - 什么时候懒惰评估没有用?