如何强制子虚拟函数首先调用其父虚拟函数
伙计们,我有一个案例,需要子类需要先调用其父虚函数,然后再调用其覆盖虚函数.
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?
谢谢.
推荐答案
对于简单的情况,您可以使用第二个私有成员函数来实现可重写行为:
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
}
};
<小时>
对于更复杂的层次结构(例如,您有多个继承级别),这是不可能的,因为任何派生类都可以覆盖任何虚拟成员函数(C++ 中没有 final
).通常可以安全地假设每个派生类都在做正确的事情.虽然我可以想到有几次我因为派生类搞砸了覆盖而遇到问题,但这些情况通常很容易调试.
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.]
相关文章