简体   繁体   English

C ++方法重载:基本和派生参数

[英]C++ method overloading: base and derived parameters

After searching around the web I did not manage to find an answer to this question: 在网上搜索后,我找不到这个问题的答案:

I have this overloaded method: 我有这个重载的方法:

foo(Base* base);
foo(Derived* derived);

In this case "Derived" is a subclass of "Base". 在这种情况下,“Derived”是“Base”的子类。
When I call: 我打电话的时候:

foo(new Derived());

I notice that always the first overloaded method is called, while I would like to achieve the opposite result (call the method which takes a "Derived*" object as a parameter). 我注意到总是调用第一个重载方法,而我想实现相反的结果(调用以“Derived *”对象作为参数的方法)。

How to solve this? 怎么解决这个? Thank you. 谢谢。

EDIT: 编辑:

Ok, this is my actual situation: 好的,这是我的实际情况:

I have an UIWidget and a UIScoreLabel class. 我有一个UIWidget和一个UIScoreLabel类。 UIScoreLabel derives from UIWidget. UIScoreLabel派生自UIWidget。 I also have a GameEvent class (Base) and a P1ScoreGameEvent class (Derived). 我还有一个GameEvent类(B​​ase)和一个P1ScoreGameEvent类(Derived)。

UIWidget: UIWidget:

virtual void handleGameEvent(GameEvent* e) { printf("ui_widget"); }

UIScoreLabel: UIScoreLabel:

virtual void handleGameEvent(P1ScoreGameEvent* e) { printf("ui_score_label"); }

This is the call: 这是电话:

UIWidget* scoreLabel = new UIScoreLabel();
scoreLabel.handleGameEvent(new P1ScoreGameEvent());

Output: 输出:

ui_widget

I don't understand what I'm doing wrong. 我不明白我做错了什么。

I actually get the opposite result from you, with the method which takes the more Derived type taking precedence. 实际上,我得到了相反的结果,使用了更多Derived类型优先的方法。 In the demo code below, the method which takes "Derived" seems to be called by default. 在下面的演示代码中,默认情况下调用“Derived”的方法。 However, you can always force it with a pointer cast. 但是,您始终可以使用指针强制转换它。

#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*)
}

Output: 输出:

Bar is on dancing!
Bar is on stage!

Note that it is bar 's methods that are called both times (this is correct polymorphic behavior!), but it is a different method of bar called by each of the overloads, to disambiguate. 请注意, bar的方法被称为两次(这是正确的多态行为!),但它是每个重载调用的一种不同bar方法,以消除歧义。

I managed to solve the problem by changing this line: 我设法通过更改此行来解决问题:

UIWidget* scoreLabel = new UIScoreLabel();

To

UIScoreLabel* scoreLabel = new UIScoreLabel();

However, even if this solves the problem, I would like to avoid using this "trick", since my code keeps a list of UIWidget* objects and calls the handleGameEvent() method on them. 但是,即使这解决了这个问题,我也想避免使用这个“技巧”,因为我的代码保留了一个UIWidget *对象列表,并对它们调用了handleGameEvent()方法。 If someone is aware of any other solution, please share it. 如果有人知道任何其他解决方案,请分享。

EDIT: 编辑:

minimal compilable example: 最小的可编译示例:

#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"
}

NB: This actually solves the problem, but the solution is not elegant because I want to have something like this: 注意:这实际上解决了问题,但解决方案并不优雅,因为我希望有这样的东西:

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"
}

在“最小可编译示例”中,handleGameEvent未声明为虚拟,因此不会应用重载。

This is because C++ does not support double dispatch. 这是因为C ++不支持双重调度。 If you declare your variable as Base, it will be treated so. 如果将变量声明为Base,则会对其进行处理。 Once you changed its type to Derived, the compiler was able to get its real type and then call the correct method. 一旦将其类型更改为Derived,编译器就能够获得其真实类型,然后调用正确的方法。

To solve this problem you may want to use a Visitor Pattern . 要解决此问题,您可能需要使用访客模式

There's a nice discussion about this in this answer . 这个答案中有一个很好的讨论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM