您可以在同一个 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 很好地描述了这种模式。