在网上搜索后,我找不到这个问题的答案:
我有这个重载的方法:
foo(Base* base);
foo(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
我不明白我做错了什么。
答案 0 :(得分:1)
我实际上得到了与你相反的结果,使用了更多Derived类型优先的方法。在下面的演示代码中,采用" Derived"似乎默认调用。但是,您始终可以使用指针强制转换它。
#include <stdio.h>
#include <iostream>
class Foo {
public:
virtual void perform() {
printf("Foo is on stage!\n");
}
virtual void dance() {
printf("Foo is on dancing!\n");
}
};
class Bar : public Foo {
public:
void perform() {
printf("Bar is on stage!\n");
}
void dance() {
printf("Bar is on dancing!\n");
}
};
int m1 (Foo* foo) {
foo->perform();
}
int m1 (Bar* foo) {
foo->dance();
}
int main(){
m1(new Bar); // Calls m1(Foo*)
m1((Foo*) new Bar); // Calls m1(Bar*)
}
输出:
Bar is on dancing!
Bar is on stage!
请注意,bar
的方法同时被调用(这是正确的多态行为!),但它是bar
的不同的方法每个重载调用,消除歧义。
答案 1 :(得分:1)
我设法通过更改此行来解决问题:
UIWidget* scoreLabel = new UIScoreLabel();
要
UIScoreLabel* scoreLabel = new UIScoreLabel();
然而,即使这解决了这个问题,我也想避免使用这个“技巧”,因为我的代码保留了一个UIWidget *对象列表,并对它们调用了handleGameEvent()方法。如果有人知道任何其他解决方案,请分享。
编辑:
最小的可编辑示例:
#include <stdio.h>
#include <iostream>
#include <vector>
class GameEvent {};
class P1ScoreGameEvent : public GameEvent {};
class UIWidget { public: virtual void handleGameEvent(GameEvent* e) { printf("ui_widget"); } };
class UIScoreLabel : public UIWidget { public: virtual void handleGameEvent(P1ScoreGameEvent* e) { printf("ui_score_label"); } };
void main()
{
UIWidget* w1 = new UIScoreLabel();
w1->handleGameEvent(new P1ScoreGameEvent()); // output: "ui_widget"
UIScoreLabel* w2 = new UIScoreLabel();
w2->handleGameEvent(new P1ScoreGameEvent()); // output: "ui_score_label"
}
N.B:这实际上解决了这个问题,但解决方案并不优雅,因为我想要这样的东西:
void main()
{
vector<UIWidget*> widgets;
widgets.push_back(new UIScoreLabel());
widgets.push_back(new UIScoreLabel());
// push more..
for (unsigned int = 0; i < widgets.size(); i++)
widgets[i]->handleGameEvent(new P1ScoreGameEvent()); // output: "ui_widget", but I want "ui_score_label"
}
答案 2 :(得分:0)
在您的&#34;最小可编辑示例&#34;中,handleGameEvent未声明为虚拟,因此不会应用重载。
答案 3 :(得分:0)
这是因为C ++不支持双重调度。如果将变量声明为Base,则会对其进行处理。一旦将其类型更改为Derived,编译器就能够获得其真实类型,然后调用正确的方法。
要解决此问题,您可能需要使用Visitor Pattern。
在this answer中对此进行了很好的讨论。