簡體   English   中英

程序為什么要這樣寫輸出?

[英]Why does the program writes output like this?

我想知道為什么這個C ++程序X:f1的輸出是什么? 是否有y對象的調用,調用Y的f1()是否合乎邏輯? 不應該有繼承嗎? 我糊塗了...

    class X {
    public:
        void f1() { cout<<"X:f1"<<endl;}
    };
    class Y : public X {
    public:
        void f1() { cout<<"Y:f1"<<endl;}
    };
    Y* y = new Y();
    void f(X* x) { x -> f1(); }
    int main () { f (y);
    system("pause");
    return 1;
    }

以及如何更改f()函數的主體和在輸出中獲得Y:f1所需的參數?

由於X::f1不是virtual ,因此對其的調用是靜態分派的,即,在這種情況下,它們是基於x的靜態類型(即X )而不是其動態類型(在本例中為Y )分派的)。

換句話說,因為X::f1不是virtual ,所以沒有考慮x在您調用f(y)時指向Y實例的事實-編譯器將對X::f1所有調用分配給Xf1 ,與x指向的對象的動態(即運行時)類型無關。

與其他語言(例如Java)不同,C ++中的成員函數默認情況下不是virtual的-您必須明確指定希望子類能夠覆蓋它們。

為了獲得您期望的輸出,您需要在X::f1添加一個virtual限定符-您不能按照建議的方式僅更改f的主體來明智地實現所需的功能,因為您正在丟棄有關x的信息動態類型,但是在這種特殊情況下,您可以更改f的參數以接受Y*而不是X*

您會遇到此問題,因為該函數未聲明為虛函數。 您需要將virtual限定符添加到Xf1以允許子類覆蓋它。

class X {
public:
    virtual void f1() { cout<<"X:f1"<<endl;}
};

class Y : public X {
public:
    virtual void f1() { cout<<"Y:f1"<<endl;}
};

如果不這樣做,則僅當編譯器知道對象的類型時,才調用Yf1 當您將其轉換為X*時,情況並非如此。 這是您觀察到的行為:

Y* y = new Y;
y->f1(); // prints "Y:f1"
X* x = y;
x->f1(); // prints "X:f1"!

以及如何更改f()函數的主體和在輸出中獲得Y:f1所需的參數?

您問題的實際答案是:

void f(Y* y) { y -> f1(); }

盡管在派生類中沒有使用具有相同名稱和簽名的非虛擬方法的感覺,除了產生難以捕捉的問題之外。

我以這種方式在編譯器中嘗試了您的代碼

#include<iostream>
using namespace std;
class X {
public:
     virtual void f1() { cout<<"X:f1"<<endl;}
  // ^^^^^^^ Note my changes here!
};
class Y : public X {
public:
    void f1() { cout<<"Y:f1"<<endl;}
};

Y* y = new Y();
void f(X* x) { x -> f1(); }

int main () {
    f(y);
    return 1 ;
}

並且輸出是Y:F1而不是X:F1如您所說,再試一次,

暫無
暫無

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

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