强制调用长链下的基类虚拟函数
Force calling base class virtual function down long chains
我的问题用更长的继承链扩展了这个问题
这是我的代码:
////////// 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
Sprite:render
所需输出:
.. 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;
}
};
我已经使用嵌套类构造函数完成并实现了您想要的内容。它相当丑陋,有很多样板,但我相信它正是你想要的。
#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;
}
严格来说,我仍然不认为有办法强迫人正确地做这件事,但使用这种方法,调用任何渲染器都会自动调用它下面的所有渲染器(这是没有办法的)。一个聪明的子类仍然可以自由地编写自己的Render子类,而无需从上面的Render类派生它,但他不会免费获得所有渲染行为,所以我认为这尽可能接近你想要的。
渲染完全在---Render
嵌套类的构造函数中完成,利用了总是为构造函数执行链接的事实。用户只需要提供一个受保护的虚拟函数MakeRender,该函数返回所需类型的渲染器引用。用户只声明MakeRender
函数这一事实或多或少地迫使他们生成类的实例,并阻止他们在构造函数之外进行渲染工作(这将破坏目的)。
如果无论派生版本如何,都希望执行ImageView::render()
的操作,为什么不创建一个私有的非虚拟ImageView::base_render()
,并在派生render()
之前或之后从ImageView::Render()
调用它?
Decorator模式在这里可能会有所帮助,但这并不是您想要的。
相关文章:
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 子类地址等于虚拟基类地址?
- 是否可以使用基类非虚拟方法中的派生类虚拟方法?
- 虚拟基类函数中派生类的大小
- 使(虚拟)函数在大多数派生类中无法访问中间基类中可访问,定义良好?
- 当键是虚拟继承中涉及的基类指针时,对 std::unordered_map 项的访问崩溃
- 基类可以声明虚拟方法但不定义它吗?仍然在派生类中定义
- 虚拟基类初始化
- googletest:测试基类具有纯虚拟方法的派生类时的核心转储
- 有没有办法在没有虚拟的情况下使用基类指针调用派生类函数
- 我是否需要在虚拟继承类的构造函数中初始化基类以解决菱形继承问题?
- 虚拟基类在内部如何工作?编译器如何解析对基方法的调用?
- 无法使用在子类中定义的虚拟getter实现基类
- C++虚拟函数:基类函数是调用的,而不是派生的
- 关于C++从派生类调用在基类中实现的虚拟函数的问题
- 派生类调用非公共基类虚拟函数
- 使用基类虚拟方法
- 强制调用基类虚拟函数
- 强制调用长链下的基类虚拟函数
- 通过派生类虚拟方法调用基类虚拟方法