我在网上搜索了一下,没有找到这个问题的答案:
我有一个重载的方法:
foo(Base* base);
foo(Derived* derived);
在这种情况下,“Derived”是“Base”的子类。
当我打电话:
foo(new Derived());
我注意到总是第一个重载的方法被调用,而我希望得到相反的结果(调用以“Derived*”对象作为参数的方法)。
如何解决这个问题?谢谢。
编辑:
好吧,这是我的实际情况:
我有一个UIWidget和一个UIScoreLabel类。UIScoreLabel从UIWidget派生。我还有一个GameEvent类(Base)和一个P1ScoreGameEvent类(Derived)。
UIWidget:
virtual void handleGameEvent(GameEvent* e) { printf("ui_widget"); }
UIScoreLabel:
virtual void handleGameEvent(P1ScoreGameEvent* e) { printf("ui_score_label"); }
这是我们的使命:
UIWidget* scoreLabel = new UIScoreLabel();
scoreLabel.handleGameEvent(new P1ScoreGameEvent());
输出:
ui_widget
我不明白我做错了什么。
4条答案
按热度按时间myzjeezk1#
这是因为C++不支持双重分派。如果你将变量声明为Base,它将被如此对待。一旦你将其类型更改为Derived,编译器就能够获取其真实的类型,然后调用正确的方法。
要解决这个问题,您可能需要使用Visitor Pattern。
在this answer中有一个很好的讨论。
wlwcrazw2#
在您“最小可编译示例”中,handleGameEvent没有声明为virtual,因此不会应用重载。
t9eec4r03#
实际上我从你那里得到了相反的结果,使用更Derived类型的方法优先。在下面的演示代码中,默认情况下似乎会调用使用“Derived”的方法。但是,您始终可以使用指针强制转换来强制调用它。
输出:
请注意,两次调用的都是
bar
的方法(这是正确的多态行为!),但为了消除歧义,每一次重载都调用了bar
的一个不同的方法。e5njpo684#
我通过改变这一行来解决这个问题:
到
然而,即使这解决了问题,我也想避免使用这个“技巧”,因为我的代码保留了一个UIWidget* 对象的列表,并对它们调用handleGameEvent()方法。如果有人知道任何其他解决方案,请分享它。
编辑:
最小可编译示例:
N.B:这实际上解决了问题,但解决方案并不优雅,因为我想有这样的东西: