我想扩展一个带有虚函数的抽象基类,并将函数名称保持为虚拟,但是在"可能"之前和之后运行代码。被覆盖的儿童功能。
以下是一个例子:
我有一个可以绘制的基类(接口):
class IDraw {
public:
virtual void do_draw(Screen *scr) = 0;
};
我希望将此接口保留在子类中并能够覆盖它, 例如,我有一个游戏类,它清理屏幕,绘制东西,然后翻转显示缓冲区:
class Game : public IDraw {
public:
// Keep the interface
// This can be overridden by sub classes
virtual void do_draw(Screen *scr) = 0; // (1)
private:
// But override the base class so if s.b. calls
// do_draw from a IDraw pointer it executes this!
void IDraw::do_draw(Screen *scr) override; // (2)
};
// Implementation of (2)
void Game::IDraw::do_draw(Screen *scr) {
// Do stuff before like clear the screen
scr->clear();
// Call the method supplied by childs
this->do_draw(scr); // (1)
// Present the drawing
scr->present();
}
由于我在子项提供的函数之前和之后都有代码,因此我不能简单地覆盖保持虚拟,因为孩子必须决定是在之前还是之后调用Game :: do_draw()//(2)。
我知道我可以简单地用不同的名称调用函数(2),但由于我需要很多类来做这种事情,所以它会以相同概念的大量名称结束。
在C ++ 11中有没有办法做这类事情?
答案 0 :(得分:2)
我希望将此接口保留在子类中并能够覆盖它,
自动情况已经如此,因为您在public
访问级别继承了它。
例如我有一个游戏类,它可以清理屏幕,绘制内容而不是翻转显示缓冲区...
... 有没有办法在C ++ 11中做这种事情?
完全独立于任何c ++ 11特性,只需编写一个抽象函数声明的实现,并添加一个额外的间接层(又名Template Method Pattern):
class Game : public IDraw {
public:
// Keep the interface
// This can be overridden by sub classes
void do_draw(Screen *scr) override {
OnPreDraw(scr);
OnDraw(scr);
OnPostDraw(scr);
}
protected:
virtual void OnPreDraw(Screen *scr) {
// Default implementation
scr->clear();
}
virtual void OnDraw(Screen *scr) = 0; // << Class is still abstract
virtual void OnPostDraw(Screen *scr) {
// Default implementation
scr->present();
}
};
这将允许在更精细的操作序列中注入Game
的任何实现,但保持基类实现的默认行为。
此外,基类仍然是抽象的,并且有效地强制任何派生类实现OnDraw()
,这实际上与do_draw()
相同。
但是因为我需要很多班级做这种事情,所以它会以相同概念的大量名字结束。
没有。至于你的概念只涉及操作
OnPreDraw(scr);
OnDraw(scr);
OnPostDraw(scr);
在那个序列中,将来不再对整个类继承层次结构进行更改。
延伸:
您也可以使用Mixin pattern类 1
执行此操作template<typename Derived>
class AbstractIDrawImpl : public IDraw {
void do_draw(Screen *scr) override {
static_cast<Derived*>(this)->OnPreDraw(scr);
static_cast<Derived*>(this)->OnDraw(scr);
static_cast<Derived*>(this)->OnPostDraw(scr);
}
// Expects public implementations
void OnPreDraw(Screen *scr) {
// Default implementation
scr->clear();
}
// Just no default implementation for
// void OnDraw(Screen *scr) << Class is still abstract
void OnPostDraw(Screen *scr) {
// Default implementation
scr->present();
}
};
上面的mixin示例可以绑定到IDraw
的任何实现,为public
,OnPreDraw()
和OnDraw()
提供OnPostDraw()
函数:
class MyGame : public AbstractIDrawImpl<MyGame> {
public:
// IDraw interface implementation
void OnPreDraw(Screen *scr) {
// Call base class implementation
AbstractIDrawImpl<MyGame>::OnPreDraw(scr);
// E.g fill my background here
}
void OnDraw(Screen *scr) {
// For each game entity call
// IDraw::do_draw(scr);
for(auto drawableEntity : drawableEntities_) {
drawableEntity->do_draw(scr);
}
}
// Skip implementation of OnPostDraw()
private:
std::vector<std::shared_ptr<IDraw>> drawableEntities_;
};
1)
Alexei Andrescou的Policy based design paradigm很好地描述了这种模式,并与Microsoft's ATL大量使用。