[英]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
所有調用分配給X
的f1
,與x
指向的對象的動態(即運行時)類型無關。
與其他語言(例如Java)不同,C ++中的成員函數默認情況下不是virtual
的-您必須明確指定希望子類能夠覆蓋它們。
為了獲得您期望的輸出,您需要在X::f1
添加一個virtual
限定符-您不能按照建議的方式僅更改f
的主體來明智地實現所需的功能,因為您正在丟棄有關x
的信息動態類型,但是在這種特殊情況下,您可以更改f
的參數以接受Y*
而不是X*
。
您會遇到此問題,因為該函數未聲明為虛函數。 您需要將virtual
限定符添加到X
的f1
以允許子類覆蓋它。
class X {
public:
virtual void f1() { cout<<"X:f1"<<endl;}
};
class Y : public X {
public:
virtual void f1() { cout<<"Y:f1"<<endl;}
};
如果不這樣做,則僅當編譯器知道對象的類型時,才調用Y
的f1
。 當您將其轉換為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.