C++ 强制沿长链调用基类虚函数

C++ 强制沿长链调用基类虚函数,c++,C++,我的问题延伸到更长的继承链 这是我的代码: ////////// View /////////////// class View{ public: void Render(){ std::cout << "View::Render" << std::endl; render(); } protected: virtual void render() = 0; }; ////////// Image

我的问题延伸到更长的继承链

这是我的代码:

////////// View ///////////////
class View{
public:
    void Render(){
        std::cout << "View::Render" << std::endl;
        render();
    }
protected:
    virtual void render() = 0;
};
////////// ImageView ///////////////
class ImageView : public View{
public:
protected:
    void render(){
        std::cout << "ImageView:render" << std::endl;
    }
};
////////// Sprite ///////////////
class Sprite : public ImageView{
public:
protected:
    void render(){
        std::cout << "Sprite:render" << std::endl;
    }
};
////////// Utility ///////////////
void Draw(View *vw){
    vw->Render();
}
////////// main ///////////////
int main(){
    std::cout << "... Draw ImageView ..." << std::endl;
    ImageView *imgvw = new ImageView;
    Draw(imgvw);
    delete imgvw;

    std::cout << "... Draw Sprite ..." << std::endl;
    Sprite *sp = new Sprite;
    Draw(sp);
    delete sp;
    
    return 0;
}
所需输出:

.. Draw ImageView ...
View::Render
ImageView:render
... Draw Sprite ...
View::Render
ImageView:render
Sprite:render
我试图只保留一个基类公共方法,它应该调用所有虚拟方法链。 C++中有可能这样吗?

,更改你的定义如下:

class Sprite : public ImageView{
public:
protected:
    void render(){
        ImageView::render(); // this calls the superclass' virtual method
        std::cout << "Sprite:render" << std::endl;
    }
};
类精灵:公共图像视图{
公众:
受保护的:
void render(){
ImageView::render();//这将调用超类的虚拟方法
std::coutPer,更改您的定义如下:

class Sprite : public ImageView{
public:
protected:
    void render(){
        ImageView::render(); // this calls the superclass' virtual method
        std::cout << "Sprite:render" << std::endl;
    }
};
类精灵:公共图像视图{
公众:
受保护的:
void render(){
ImageView::render();//这将调用超类的虚拟方法

std::cout如果您希望执行
ImageView::render()
的操作,而不管派生版本说什么,为什么不创建一个私有的、非虚拟的
ImageView::base_render()
并在派生的
render()之前或之后从
ImageView::render()
调用它呢

如果您希望执行
ImageView::render()
的操作,而不管派生版本说什么,为什么不创建一个私有的、非虚拟的
ImageView::base_render()
并在派生
render()之前或之后从
ImageView::render()
调用它呢

装饰器模式在这里可能会有所帮助,但这并不完全是您想要的。

装饰器模式在这里可能会有所帮助,但也不完全是您想要的。

我已经使用嵌套类构造函数完成并实现了您想要的内容。它相当丑陋,有很多样板文件,但是我相信这正是你想要的

#include <string>
#include <iostream>

using namespace std;

class View
{
protected:
    class ViewRender
    {
    public:
        ViewRender(const View &v) 
        {
            cout << "ViewRender:constructor" << endl;
        }
    };

    // returns a reference to a temporary.  I'm not sure how to avoid doing this
    // the reference isn't actually used, and we can't pass it a reference to one
    // and have it populate it since the trick is in the constructor.

    virtual ViewRender &MakeRender() = 0;
public:
    void Render() { MakeRender(); }
};

class ImageView : public View
{
protected:
    class ImageViewRender : public View::ViewRender
    {
    public:
        ImageViewRender(const View &v) : ViewRender(v)
        {
            cout << "ImageViewRender:constructor" << endl;
        }
    };

    virtual ImageViewRender &MakeRender() { return ImageViewRender(*this); }
};

class Sprite : public ImageView
{
protected:
    class SpriteRender : public ImageView::ImageViewRender
    {
    public:
        SpriteRender(const View &v) : ImageViewRender(v)
        {
            cout << "SpriteRender:constructor" << endl;
        }
    };

    virtual SpriteRender &MakeRender() { return SpriteRender(*this); }
};

class AwesomeSprite : public Sprite
{
protected:
    class AwesomeSpriteRender : public Sprite::SpriteRender
    {
    public:
        AwesomeSpriteRender(const View &v) : SpriteRender(v)
        {
            cout << "AwesomeSpriteRender:constructor" << endl;
        }
    };

    virtual AwesomeSpriteRender &MakeRender() { return AwesomeSpriteRender(*this); }
};

int main()
{
    AwesomeSprite as;
    ImageView &iv = as;

    cout << "rendering AwesomeSprite..." << endl;
    as.Render();

    cout << "rendering Awesome (downcast to ImageView)..." << endl;
    iv.Render();

    system("pause");
    return 0;
}
#包括
#包括
使用名称空间std;
类视图
{
受保护的:
类ViewRender
{
公众:
ViewRender(常量视图和v)
{

cout我已经使用嵌套类构造函数完成并实现了您想要的内容。它相当难看,并且有很多样板文件,但我相信它完全满足您的需要

#include <string>
#include <iostream>

using namespace std;

class View
{
protected:
    class ViewRender
    {
    public:
        ViewRender(const View &v) 
        {
            cout << "ViewRender:constructor" << endl;
        }
    };

    // returns a reference to a temporary.  I'm not sure how to avoid doing this
    // the reference isn't actually used, and we can't pass it a reference to one
    // and have it populate it since the trick is in the constructor.

    virtual ViewRender &MakeRender() = 0;
public:
    void Render() { MakeRender(); }
};

class ImageView : public View
{
protected:
    class ImageViewRender : public View::ViewRender
    {
    public:
        ImageViewRender(const View &v) : ViewRender(v)
        {
            cout << "ImageViewRender:constructor" << endl;
        }
    };

    virtual ImageViewRender &MakeRender() { return ImageViewRender(*this); }
};

class Sprite : public ImageView
{
protected:
    class SpriteRender : public ImageView::ImageViewRender
    {
    public:
        SpriteRender(const View &v) : ImageViewRender(v)
        {
            cout << "SpriteRender:constructor" << endl;
        }
    };

    virtual SpriteRender &MakeRender() { return SpriteRender(*this); }
};

class AwesomeSprite : public Sprite
{
protected:
    class AwesomeSpriteRender : public Sprite::SpriteRender
    {
    public:
        AwesomeSpriteRender(const View &v) : SpriteRender(v)
        {
            cout << "AwesomeSpriteRender:constructor" << endl;
        }
    };

    virtual AwesomeSpriteRender &MakeRender() { return AwesomeSpriteRender(*this); }
};

int main()
{
    AwesomeSprite as;
    ImageView &iv = as;

    cout << "rendering AwesomeSprite..." << endl;
    as.Render();

    cout << "rendering Awesome (downcast to ImageView)..." << endl;
    iv.Render();

    system("pause");
    return 0;
}
#包括
#包括
使用名称空间std;
类视图
{
受保护的:
类ViewRender
{
公众:
ViewRender(常量视图和v)
{


事实上,这是我试图避免的事情。我知道这听起来可能很疯狂,但我只想知道,如果不显式调用超类的方法,是否可以实现结果?不是的,您必须显式执行。您可以通过从
Render()调用每个方法来强制执行此行为但这并不能真正避免问题,只是把它移到别处。A.好了,谢谢!我会继续观察答案,然后我将把这个答案标记为正确的:)代码> S/SuffCys/BaseCys/<代码>,<代码> S/方法/成员函数/<代码>……某人有适当的C++术语来学习。每种语言都叫它们。g.Sub-和super-是互补前缀。Java调用成员函数方法。我使用很多语言,很难跟踪。至少你永远不会听到我说“Accessor”或“Mutator”。实际上,这是我试图避免的事情。我知道这听起来可能很疯狂,但我只是想知道是否有可能用是否显式调用超类的方法?不是,您必须显式执行。您可以通过从
Render()调用每个方法来强制执行此行为但这并不能真正避免问题,只是把它移到别处。A.好了,谢谢!我会继续观察答案,然后我将把这个答案标记为正确的:)代码> S/SuffCys/BaseCys/<代码>,<代码> S/方法/成员函数/<代码>……某人有适当的C++术语来学习。每种语言都叫它们。g不同的.Sub和super是互补的前缀。Java调用成员函数方法。我使用很多语言,很难跟踪。至少你不会听到我说“Accessor”或“Mutator”。
ImageView::Render()
不是真实的,该方法在
视图中声明。让我们假设它确实存在。这将始终调用
ImageView::render()
,但不会调用任何中间
render()
s,如果它们存在的话。假设有一个子类
Sprite
AwesomeSprite
ImageView::Render
将因此调用
ImageView::base\u Render()
,它将调用
ImageView::Render()
,然后它将调用
Render()
,解析为
AwesomeSprite::Render()
,跳过
Sprite::render()
。您可能能够找到一种方法使它与构造函数(它们确实像这样)一起工作,但不能与普通方法一起工作。我正在试图找到一种方法,使render()在视图类中,只有公共方法可用,所有派生类只是神奇地调用继承链中的所有方法。但是现在我意识到,C++(或任何语言)可能是不可能的。:)继承的全部要点是能够有选择地重写行为,因此我想不出任何语言的任何实现都无法强制重写行为(构造函数除外,构造函数就是这样做的)说真的,只需用模板方法模式编译非虚继承模式,你就可以去了。我猜你是在建议这样的事情,它解决了这个问题,但是我在用C++探索一些疯狂的事情,在这里我不需要明确地调用基类的方法。<代码> IVIEVIEW::
不是真实的,该方法在
视图中声明。让我们假设它确实存在。这将始终调用
ImageView::render()
,但不会调用任何中间
render()
s,如果它们存在的话。假设有一个子类
Sprite
AwesomeSprite
ImageView::Render
将因此调用
ImageView::base\u Render()
,它将调用
ImageView::Render()
。然后它将调用
Render()
,whic