簡體   English   中英

從基對象上的 C++ 類調用重載的派生函數不會調用重載函數

[英]Call overloaded, derived function from C++ class on base object does not call the overloaded function

這是一個簡化的示例( OnlineGDB ):

#include <iostream>

using namespace std;

class Base {
public:
    virtual ~Base() {}
    virtual int test(Base* parent) = 0;
};

class Test : public Base {
public:
    ~Test() {}
    int test(Base* parent) { return 10; }
    int test(Test* parent) { return 20; }
};

int main(int argc, char* argv[]) {
    Test* test = new Test();
    Base* base = test;

    cout << test->test(test) << endl; // prints 20
    cout << base->test(test) << endl; // prints 10
    
    return 0;
}

我希望兩個調用都返回20 ,因為參數的類型是Test ,但第二個調用返回10

我知道我可以做dynamic_cast<Test*>(base)->test(test)並且它再次工作,但實際上我有更多從Base派生的類。 我當然可以做某事。 像這樣:

auto test1 = dynamic_cast<Test*>(base);
if (test1) {
    test1->test(test);
}

auto test2 = dynamic_cast<Test2*>(base);
if (test2) {
    test2->test(test);
}

...

但是對於從Base派生的任何新類,這都需要進行調整,並且代碼中有多個部分必須這樣做。

有什么辦法,我可以保留base->test(test)或 sth。 類似於根據參數類型獲取“正確”值?

base->test(test) 

base是指向Base的指針。 Base有一個類方法叫做test() 這就是被調用的類方法。 由於該類方法的參數是Base * ,因此test被轉換為。 這就是 C++ 中類型轉換的工作原理。

base指向派生對象的基類,它覆蓋了該虛擬方法。 派生類中采用Base *的被覆蓋方法被調用,因為這是被覆蓋的方法。

指針在轉換之前指向Test *的事實並不重要。 Base中沒有將Test *作為參數的函數,唯一一個將Base *作為參數的函數,所以這就是被調用的函數。

當您轉換一個類時,最具體的信息與您將其轉換到的層次結構中的類型相關。

Base vtable沒有該重載,因此編譯器無法在編譯時知道另一個重載存在。

如果您考慮如何實現動態調度,那么為什么您的代碼無法正常工作是微不足道的,我不明白它是如何實現的。

您應該提供您正在嘗試解決的確切問題,因為您嘗試做的事情可能有不同的解決方案,因為它看起來像一個 XY 問題。

暫無
暫無

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

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