您可以在同一个 class 中覆盖纯虚函数吗?
Can you override a pure virtual function within the same class?
我想用虚函数扩展一个抽象基class并保持函数名称为虚函数,但是"possibly"前后的运行代码被覆盖了child函数。
这是一个例子:
我有一个可以画东西的基础class(界面):
class IDraw {
public:
virtual void do_draw(Screen *scr) = 0;
};
我想将此接口保留在子classes 中并能够覆盖它,
例如,我有一个用于游戏的 class,它可以清洁屏幕、绘制内容并翻转显示缓冲区:
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();
}
因为我在 child 提供的函数之前和之后都有代码,所以我不能简单地覆盖保持它虚拟,因为 child 必须决定是否调用 Game::do_draw() // ( 2) 之前或之后。
我知道我可以简单地用不同的名称调用函数 (2),但由于我需要很多人 class 做这种事情,所以同一概念将以很多名称结尾。
有没有办法在 C++11 中做这种事情?
I want to keep this interface in subclasses and be able to override it,
这已经自动发生了,因为您在 public
访问级别继承了它。
for example I have a class for a Game, which cleans the screen, draw stuff and than flip the display buffer ...
...
Is there any way to do this sort of thing in 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
的任何实现,但保留基本 class 实现的默认行为。
此外,基础 class 仍然是抽象的,并且有效地强制任何派生的 class 实现 OnDraw()
,这实际上与 do_draw()
.
相同
but since I need many class doing this kind of stuff it will end with plenty of names for the same concept.
没有。至于你的概念只涉及操作
OnPreDraw(scr);
OnDraw(scr);
OnPostDraw(scr);
按照这个顺序,以后整个 class 继承层次结构都不会改变。
延伸:
您也可以使用 Mixin pattern classes1
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
的任何实现,它为 OnPreDraw()
、 OnDraw()
和 OnPostDraw()
提供 public
函数:
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 and heavily used with Microsoft's ATL 很好地描述了这种模式。
我想用虚函数扩展一个抽象基class并保持函数名称为虚函数,但是"possibly"前后的运行代码被覆盖了child函数。
这是一个例子:
我有一个可以画东西的基础class(界面):
class IDraw {
public:
virtual void do_draw(Screen *scr) = 0;
};
我想将此接口保留在子classes 中并能够覆盖它, 例如,我有一个用于游戏的 class,它可以清洁屏幕、绘制内容并翻转显示缓冲区:
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();
}
因为我在 child 提供的函数之前和之后都有代码,所以我不能简单地覆盖保持它虚拟,因为 child 必须决定是否调用 Game::do_draw() // ( 2) 之前或之后。
我知道我可以简单地用不同的名称调用函数 (2),但由于我需要很多人 class 做这种事情,所以同一概念将以很多名称结尾。
有没有办法在 C++11 中做这种事情?
I want to keep this interface in subclasses and be able to override it,
这已经自动发生了,因为您在 public
访问级别继承了它。
for example I have a class for a Game, which cleans the screen, draw stuff and than flip the display buffer ...
... Is there any way to do this sort of thing in 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
的任何实现,但保留基本 class 实现的默认行为。
此外,基础 class 仍然是抽象的,并且有效地强制任何派生的 class 实现 OnDraw()
,这实际上与 do_draw()
.
but since I need many class doing this kind of stuff it will end with plenty of names for the same concept.
没有。至于你的概念只涉及操作
OnPreDraw(scr);
OnDraw(scr);
OnPostDraw(scr);
按照这个顺序,以后整个 class 继承层次结构都不会改变。
延伸:
您也可以使用 Mixin pattern classes1
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
的任何实现,它为 OnPreDraw()
、 OnDraw()
和 OnPostDraw()
提供 public
函数:
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 and heavily used with Microsoft's ATL 很好地描述了这种模式。