我想知道为什么这个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所需的参数?
答案 0 :(得分:7)
由于X::f1
不是virtual
,因此会静态调度对它的调用,即在这种情况下,它们会根据x
的静态类型(X
进行调度。 1}})而不是动态类型(在这种情况下是Y
)。
换句话说,因为X::f1
不是virtual
,x
在您致电Y
时指向f(y)
的实例这一事实没有考虑 - 无论对象的动态(即运行时)类型如何,编译器都会将对X::f1
的所有调用都调度到X
&#39; f1
由x
指出。
与其他语言(例如Java)不同,默认情况下,C ++中的成员函数不是virtual
- 您必须明确指定您希望子类能够覆盖它们。
要获得您期望的输出,您需要向virtual
添加X::f1
限定符 - 您只需更改f
的正文即可明智地达到您想要的效果如您所建议,因为您放弃了有关x
动态类型的信息,但您可以更改f
的参数以接受Y*
而不是X*
{1}}在这种特殊情况下。
答案 1 :(得分:4)
您遇到此问题,因为该功能未声明为虚拟。您需要将virtual
限定符添加到X
&#39; f1
,以允许子类覆盖它。
class X {
public:
virtual void f1() { cout<<"X:f1"<<endl;}
};
class Y : public X {
public:
virtual void f1() { cout<<"Y:f1"<<endl;}
};
如果您不这样做,只有在编译器知道对象的类型时才会调用Y
&#39; f1
。将其转换为X*
时不是这种情况。这是您观察到的行为:
Y* y = new Y;
y->f1(); // prints "Y:f1"
X* x = y;
x->f1(); // prints "X:f1"!
答案 2 :(得分:1)
如何更改f()函数的主体和获取的参数 Y:输出处的f1?
您问题的实际答案是:
void f(Y* y) { y -> f1(); }
虽然没有太多意义,在派生类中使用相同名称和签名的非虚方法,除了产生难以捕获的问题。
答案 3 :(得分:0)
我以这种方式在我的编译器中尝试了你的代码
#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
,因为你说再试一次,