簡體   English   中英

C ++方法重載:基本和派生參數

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

在網上搜索后,我找不到這個問題的答案:

我有這個重載的方法:

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

在這種情況下,“Derived”是“Base”的子類。
我打電話的時候:

foo(new Derived());

我注意到總是調用第一個重載方法,而我想實現相反的結果(調用以“Derived *”對象作為參數的方法)。

怎么解決這個? 謝謝。

編輯:

好的,這是我的實際情況:

我有一個UIWidget和一個UIScoreLabel類。 UIScoreLabel派生自UIWidget。 我還有一個GameEvent類(B​​ase)和一個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

我不明白我做錯了什么。

實際上,我得到了相反的結果,使用了更多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方法,以消除歧義。

我設法通過更改此行來解決問題:

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

注意:這實際上解決了問題,但解決方案並不優雅,因為我希望有這樣的東西:

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未聲明為虛擬,因此不會應用重載。

這是因為C ++不支持雙重調度。 如果將變量聲明為Base,則會對其進行處理。 一旦將其類型更改為Derived,編譯器就能夠獲得其真實類型,然后調用正確的方法。

要解決此問題,您可能需要使用訪客模式

這個答案中有一個很好的討論。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM